3
votes

I noticed PHP behaves differently depending on whether a class is subclassing a concrete base class or implementing an abstract base class method or interface with respect to homogeny in method signatures. Consider these two examples

//----------------------------
// 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

Here's the output

Strict Standards: Declaration of D::blah() should be compatible with C::blah(ArrayAccess $a) PHP Fatal error: Declaration of B::blah() must be compatible with A::blah(ArrayAccess $a)

My question - Why would PHP treat these two scenarios differently, historical reasons perhaps? Seems to me like the same problem either way.

I suppose you can get away with it in the concrete case since the subclass doesn't have to call the parent class' implementation in its implementation. Either way, I'm still curious.

1
Maybe interesting for you: php.net/manual/en/… -> When overriding methods, the parameter signature should remain the same or PHP will generate an E_STRICT level error ... And interfaces: php.net/manual/en/… -> The class implementing the interface must use the exact same method signatures ... failure to do so will result in a fatal error ... I think the thing is, that in the first case you should use the same signature and the other can't workRizier123
With an interface you are "forcing" the class which implements it to implement all methods. When you extend from another class you can overwrite it and you just "should" use the same signature when you do so, but you don't have toRizier123
Thanks for these links, but it doesn't speak to the why, which is really what I'm after. The explanations from the manual are no more informative than the error messages themselves.quickshiftin

1 Answers

0
votes

I don't have the formal words to explain the difference but here is how I see things.

An interface is a public contract for an implementation. As a contract, you must follow the rules defined in the interface. Not following them break the contract, so that's a fatal error.

A class extension may define its own rules. These rules should be similar to the base class otherwise things get a bit weird when you swap an implementation by an other. But if rules are differents but implementation is correctly handled, that's "just" a strict error.