PHP 5.4: 为什么类可以使用不同的签名覆盖Trait方法?

12

我想知道在当前PHP 5.4实现中为什么会出现这种行为,是否有任何合理的理由:

trait T {
    public function test(PDO $pdo) {}
}

class C {
    use T;
    public function test(DOMDocument $dom) {}
}

我曾认为,一个类使用trait应该保证这个类有特定的接口可用。但是在这里,如果我们不小心覆盖了trait方法以达到其他目的,就算是与经典继承一样,我们也不会收到Strict Standards通知。
这是否是特意被允许的?为什么?
1个回答

29
这种行为是有文档记录的。来自php.net (http://php.net/manual/en/language.oop5.traits.php):
从一个基类继承的成员被Trait插入的成员覆盖。优先顺序是当前类的成员优先于Trait方法,而Trait方法优先于继承的方法。
这里没有通知的原因。
编辑:
我看了一些更严肃的文献来阐明这个话题 :)。看起来这样的行为是Trait定义的一部分。它们被设计成以这种方式工作。这是来自研究“Traits: Composable Units of Behavior”(面向对象编程欧洲会议论文集)的内容:
Trait组合的另一个特性是组合顺序不重要,因此必须显式消除冲突的Trait方法(参见第3.5节)。在类中定义的方法和包含的Trait定义的方法之间的冲突使用以下两个优先规则解决。
- 类方法优先于Trait方法。 - Trait方法优先于超类方法。这是遵循平铺属性的,该属性指出Trait方法表现得好像它们是在类本身中定义的。
你可以在这里阅读更多: http://scg.unibe.ch/archive/papers/Scha03aTraits.pdf

谢谢您的回答,它确实说类可以重写trait的方法,但并没有说明为什么可以使用不同的签名来重写它! - BenMorel
据我所知,PHP中的traits与继承相同,可以覆盖方法,这意味着没有签名检查,只有方法名称。 - Timur
@Eugene:我理解你的观点,但这仍然无法解释为什么在类方法优先级的情况下忽略了方法的签名。在我看来,这样的冲突(类方法覆盖具有不兼容签名的特征方法)应该引发一个通知——只有当签名不同时才会发生;如果它们相等,则适用优先规则。我是否还有什么遗漏,或者PHP中缺少了什么? - BenMorel
@Timur:在继承中,会出现“严格标准”通知,这就是我的问题所在。 - BenMorel
@Benjamin 哦...不知道呢。如果你真的想知道,我们可以查看PHP的源代码来了解发生了什么 :) - Timur

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