严格标准与致命错误 / 具体扩展与抽象实现

3
我注意到PHP在处理方法签名的一致性方面,在子类继承具体基类或实现抽象基类方法或接口时表现不同。请看以下两个例子:
//----------------------------
// Strict Error
//----------------------------
class C { function blah(ArrayAccess $a) {} }

class D extends C { function blah($a) {} } // <- No type-hint in subclass method

//----------------------------
// Fatal Error
//----------------------------
interface A { function blah(ArrayAccess $a); }

class B implements A { function blah($a) {} } // <- No type-hint in subclass method

这里是输出结果:

严格标准:D的blah()声明应与C :: blah(ArrayAccess $ a)兼容 PHP致命错误:B的blah()声明必须与A :: blah(ArrayAccess $ a)兼容

我的问题 - 为什么PHP会以不同的方式处理这两种情况,历史原因可能吗?在我看来,两种情况都是同样的问题。
我认为在具体情况下你可以做到这一点,因为子类在其实现中不必调用父类的实现。无论如何,我仍然很好奇。

也许对你有趣:http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends -> 当覆盖方法时,参数签名应该保持不变,否则PHP会生成E_STRICT级别的错误... 而接口:http://php.net/manual/en/language.oop5.interfaces.php#language.oop5.interfaces.implements -> 实现接口的类必须使用完全相同的方法签名...否则将导致致命错误... 我认为问题在于,在第一种情况下,你应该使用相同的签名,而另一种情况则行不通。 - Rizier123
通过接口,你可以“强制”实现它的类来实现所有方法。当你从另一个类继承时,你可以覆盖它,但你只需要在这样做时使用相同的签名,而不是必须这样做。 - Rizier123
谢谢这些链接,但它们并没有解释为什么,而这才是我真正想知道的。手册中的解释并没有比错误信息本身更有意义。 - quickshiftin
1个回答

0

我没有正式的词汇来解释这个区别,但是我可以这样理解。

接口是一个实现的公共契约。作为契约,你必须遵循接口中定义的规则。不遵守规则会破坏契约,这是一个致命错误。

类扩展可以定义自己的规则。这些规则应该与基类相似,否则当你用另一个实现替换时,事情会变得有点奇怪。但是如果规则不同但实现正确处理,那只是一个"严格的"错误。


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