簡體   English   中英

如何覆蓋具有參數類型提示集的 php function?

[英]How can I overwrite a php function that has a argument type hint set?

我正在嘗試用我自己的功能擴展 package。 但是 package 代碼在 function 調用中有類型提示,指向屬於 package 的其他類。我只是在尋找修改代碼的方法。

有關我在https 上嘗試做的事情的更多詳細信息://laracasts.com/discuss/channels/general-discussion/type-hint-hell

我曾嘗試更改代碼以使用接口和抽象,但我似乎無法阻止"Declaration of class.... must be compatible with"錯誤。

簡而言之,這就是我想要做的。

package 具有此類設置。

class ClassA {}

class ClassB {
    public function makeClassA(ClassA $classA) : ClassA
    {
        return $classA;
    }
}

這就是我想要做的。

class ClassANew {}

class ClassC extends ClassB {
    public function makeClassA(ClassANew $classA) : ClassANew
    {
        return $classA;
    }
}

我收到以下錯誤,

“PHP 致命錯誤:ClassC::makeClassA(ClassANew $classA) 的聲明:ClassANew 必須與 ClassB::makeClassA(ClassA $classA):ClassA 兼容”

我知道我可以分叉代碼並從ClassB中刪除鎖定的classA ,但我試圖不這樣做。

如果我要分叉代碼,我會研究如何維護原始代碼的前提。 因此,我嘗試將ClassB中的ClassA引用更改為ClassAInterface ,但我得到了同樣的錯誤。

我正在嘗試做的事情可能嗎?

不,這是不可能的。

看看這里,原因是: 為什么重寫方法參數違反了PHP中的嚴格標准?

這是一個小技巧,但它的特性在過去或已經使用和測試過程中不會引起安全問題

我知道這不是你真正需要的東西,但它可以完全解決你的問題,同時保持安全和強制方法的回報

class ClassA {}

class ClassB {
    public function makeClassA_ClassB(ClassA $classA) : ClassA
    {
        return $classA;
    }
    function __call($function_name, $argument){
        if ($function_name==="makeClassA" && $argument[0] instanceof ClassA ) return $this->makeClassA_ClassB($argument[0]);
    }
}
class ClassANew {}

class ClassC extends ClassB {
    public function makeClassA_ClassC(ClassANew $classA) : ClassANew
    {
        return $classA;
    }
    function __call($function_name, $argument){
        if ($function_name==="makeClassA" && $argument[0] instanceof ClassANew ) return $this->makeClassA_ClassC($argument[0]);
    }
}

$t=new ClassC();
$t2=new ClassANew();
var_dump($t->makeClassA($t2)); // object(ClassANew)#212 (0) { }

$t=new ClassB();
$t2=new ClassA();
var_dump($t->makeClassA($t2)); // object(ClassA)#212 (0) { }

好的,所以我終於找到了問題所在。 我必須保持原始引用的返回類型相同。 之后它現在工作正常。

namespace Original;

class ClassExtra {}

class ClassA {
    public function __construct($container, ClassB $classB) {}
}

class ClassB {
    public function __construct(ClassExtra $classExtra) {}
}

class ClassC {
    public $classB;
    public $containers;
    public function __construct(ClassB $classB) {
        $this->classB = $classB;
    }
    public function container(string $container = 'default'): ClassA
    {
        $this->containers[$container] = new ClassA($container, $this->classB);
        return $this->containers[$container];
    }
}

Namespace Changes;

Class NewClassA extends \Original\ClassA {}
Class NewClassB extends \Original\ClassB {}
Class NewClassC extends \Original\ClassC {
    public function container(string $container = 'default'): \Original\ClassA
    {
        $this->containers[$container] = new NewClassA($container, $this->classB);
        return $this->containers[$container];
    }
}

$classC = new \Original\ClassC(new \Original\ClassB(new \Original\ClassExtra()));
var_dump(get_class($classC->container('test')));
/* string(15) "Original\ClassA" */

$classC = new NewClassC(new NewClassB(new \Original\ClassExtra()));
var_dump(get_class($classC->container('test')));
/* string(17) "Changes\NewClassA" */

那應該是可能的:

// just an example
class ClassA {} // the class within the used package
class ClassANew {} // your own class

// ClassB is the parent class, the one in the package
class ClassC extends ClassB {
    public function makeClassA(ClassA|ClassANew $classA)
    {
        return $classA;
    }
}

確保每個類/接口都有正確的 inheritance。

更多詳情: https://www.php.net/manual/en/language.oop5.variance.php

但是,您不得完全更改父級 function 的邏輯。出於某種原因,object 有一個擴展/實現。
如果您只想擁有一個僅共享名稱的方法,請不要將新的 object 作為前一個 class 的子 class 來實現。class 應該只從前一個 class 繼承,如果它共享目的。
舉個例子,說明我想說的:

制作一個實現“Countable”的 class“Countie”只是為了有一個方法“count”是沒有意義的:

class Countie implements \Countable {
    private int $num = 0;
    public function count() {
        foreach ($i = 1; $i <= $this->num; $i++) {
          echo $i;
        }
    }
}

暫無
暫無

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

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