特质中的构造函数定义如何产生冲突?

5
在PHP 5.4.9中,以下示例会触发致命错误"B has colliding constructor definitions coming from traits"
trait T {
    public function __construct () {
        echo __CLASS__ . ": constructor called.\n";
    }
}

class A {
    use T;
}

class B extends A {
    use T;
}

当trait中包含与构造函数不同的方法时,没有问题,当构造函数实际上被复制到类中(不使用traits,“语言辅助复制和粘贴”功能)也没有问题。
那么这里的构造函数有什么特别之处呢?PHP难道不能找出其中一个覆盖了另一个吗?我在手册中找不到任何关于这个限制的信息。 这个相关问题提到了解决问题的方法(通过为trait方法使用别名),但没有提到导致问题的原因。
1个回答

3

尝试以下代码,看看会发生什么:

class A {
    use T;
    use T;
}

因为您通过扩展A并再次对B使用T而实际上编写了这个。

如果您需要在基类和子类中使用trait T,请仅在基类中使用它。

如果您只需要在子类中使用它,请仅在叶子子类中使用它。


在这种情况下,我会收到一个不同的错误消息:“Trait method __construct has not been applied, because there are collisions with other trait methods on A”。而且,导入的方法是构造函数还是其他方法并没有区别。问题中的示例对于其他方法可以正常工作,只有构造函数表现不同。 - Zilk
@hakre 但是它没有解释为什么另一种方法似乎完全正常。是吗? - SteAp
2
好的,这个构造函数。http://lxr.php.net/xref/PHP_5_4/Zend/zend_compile.c#3650 / http://lxr.php.net/xref/PHP_5_4/Zend/zend_compile.c#3675 - 这个魔术方法相关的,只是构造函数是这些魔术方法中的一个特殊的。这可能是为了安全起见,以防 PHP 的运行时出现问题(而不是为了您的代码安全)。 - hakre
@hakre:好吧,我不能反驳源代码 :) 我希望他们能添加一条评论来解释为什么这不可能,但我想这已经是我能得到的最接近答案了。谢谢! - Zilk
有点晚了,但你可以在版本库中进行一些责备,以找出问题(历史记录仅通过www进行,因此您不需要自己检查整个历史记录)。注释与提交一起,例如https://github.com/php/php-src/commit/e14354af21c9188582ef454696163cf68c7677ce,这个是通过责备找到的:https://github.com/php/php-src/blame/PHP-5.4/Zend/zend_compile.c - 祝你好运,对我来说有点晚了 :) 我敢打赌,如果你深入挖掘,你会发现一些漏洞。 - hakre
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接