如何覆盖已设置参数类型提示的php函数?

时间:2019-04-09 13:13:33

标签: php class overwrite hint

我正在尝试使用自己的功能扩展软件包。但是,程序包代码在函数调用中具有对作为程序包一部分的其他类的类型提示。 我只是在寻找一种修改代码的方法。

有关我正在尝试做什么的更多详细信息 https://laracasts.com/discuss/channels/general-discussion/type-hint-hell

我尝试过更改代码以使用接口和摘要,但是我似乎无法防止发生"Declaration of class .... must be compatible with"错误。

这就是我想要做的。

程序包具有这种设置。

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兼容”

我知道我可以分叉代码并从classA中删除锁定的ClassB,但是我试图不这样做。

如果我要分叉代码,那么我研究了如何保持原始代码的前提。因此,我尝试将ClassA中的ClassB引用更改为ClassAInterface,但是遇到相同的错误。

我想做的是可能的吗?

3 个答案:

答案 0 :(得分:3)

答案 1 :(得分:0)

这是一个小技巧,但它的独特性不会在过去或已经使用和测试过的情况下不会引起安全问题

我知道这不是您真正需要的,但是它可以在确保安全性和强制返回方法的同时彻底解决您的问题

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) { }

答案 2 :(得分: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" */