簡體   English   中英

PHP中的多態靜態和非靜態函數

[英]polymorphic static and non-static functions in PHP

我想用PHP創建一個簡單的Path類。 我決定使用一些類似多態的機制來實現它,但是我發現對靜態和非靜態函數都無法做到。 您是否有任何想法如何以一種優雅的方式實現absolute()函數?

class Path {

    private $path = '';

    // Some code here [...]

    public function absoulte() {
        return "http://$_SERVER[HTTP_HOST]$this->path";
    }

    public static function absoulte($path) {
        return "http://$_SERVER[HTTP_HOST]$path";
    }
}

您可以嘗試使用“ __callStatic”。 如果您在此類上調用任何靜態函數,它將觸發。 “ $ name”將成為方法名稱,“ $ arguments”是傳遞的任何參數。 :d

class Path {

    private $path = '';

    // Some code here [...]

    public function absoulte() {
        return "http://$_SERVER[HTTP_HOST]$this->path";
    }

   public static function __callStatic($name,$arguments) {
       if ($name == "absoulte") {  return "http://$_SERVER[HTTP_HOST]$arguments"; }
   }
}

好的,我會嘗試一下,您看它是否對您有幫助。 :)

我認為實際上有很多方法可以實現您所描述的公共接口,盡管它們似乎對代碼和維護來說都相當復雜。 因此,我的建議是,如果沒有必要,不要走這條路。 我會舉一些例子...


可能的解決方案1:的使用__call__callStatic

我們可以簡單地使用__call__callStatic作為我們方法的代理,並使用稍微不同的參數調用實際方法。 頂部的PhpDoc應該支持IDE了解此處的情況。

/**
 * @method string absolute()
 * @method static string absolute(string $path)
 */
class Path
{
    protected $path;

    public function __construct(string $path)
    {
        $this->path = $path;
    }

    public function __call(string $name, array $args)
    {
        if ($name === 'absolute') {
            return self::getAbsolutePath($this->path);
        }

        // ... other functions ...
    }

    public function __callStatic(string $name, array $args)
    {
        if ($name === 'absolute' && count($args) >= 1) {
            return self::getAbsolutePath($args[0]);
        }

        // ... other functions ...
    }

    private static function getAbsolutePath(string $path): string
    {
        return "http://{$_SERVER[HTTP_HOST]}{$path}";
    }
}

可能的解決方案2:對執行環境做出反應

因為我們可以以靜態方式也可以以非靜態方式訪問PHP中的方法,所以我們只需要簡單地使用信息即可返回正確的結果。

/**
 * @method string absolute()
 * @method static string absolute(string $path)
 */
class Path
{
    protected $path;

    public function __construct(string $path)
    {
        $this->path = $path;
    }

    public function absolute(?string $path): string
    {
        if (isset($this) && $this instanceof self) {
            $path = $this->path;
        }

        return "http://{$_SERVER[HTTP_HOST]}{$path}";
    }
}

其他解決方案

我認為還有其他方法可以實現此目的,可能是通過使用代理類來實現的。 但是,正確的方法確實還取決於我們迄今為止所看到的其他要求。 因為$path一個參數很容易處理,但是您的類變得越復雜,實現不同場景的工作就越多。

總而言之,我想談談我的評論:如果有解決方案,請嘗試不兩次實施。 稍后您會發現自己在多個地方尋找bug的情況。 因此,最好是只有兩個具有相同實現的不同接口。 它實際上甚至可以說是有意義的,因為在靜態和非靜態環境中,相同的方法名稱不一定都有意義。 因此,請考慮使用如下所示的內容:

/**
 * @method string absolute()
 * @method static string absolute(string $path)
 */
class Path
{
    protected $path;

    public function __construct(string $path)
    {
        $this->path = $path;
    }

    public function getAbsolutePath(): string
    {
        return self::absolute($this->path);
    }

    public static function absolute(string $path): string
    {
        return "http://{$_SERVER[HTTP_HOST]}{$path}";
    }
}

它已經解決了,但也許會幫助其他人。 這是使用func_num_args()func_get_arg()函數的另一種方法,也可以正常使用。

class Path {

    private $path = '';

    // ...

    public function absolute() {
        switch (func_num_args()) {
            case 0: return "http://" . $_SERVER[HTTP_HOST] . $this->path;
            case 1: return "http://" . $_SERVER[HTTP_HOST] . func_get_arg(0);
            default: trigger_error("Invalid number of arguments", E_USER_ERROR);
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM