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


Strict standards vs fatal error / concrete extension vs abstract implementation

我注意到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会区别对待这两种场景,也许是历史原因?在我看来,无论哪种方式都是同样的问题。

我想在具体的情况下,你可以逃脱它的惩罚,因为子类在实现中没有调用父类的实现。不管怎样,我还是很好奇。

我没有正式的词语来解释区别,但以下是我对事物的看法。

接口是实现的公共契约。作为合同,您必须遵守接口中定义的规则。不跟随他们违反了合同,所以这是一个致命的错误。

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