[英]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.