This LSP violation raises a Fatal Error:
abstract class AbstractService { }
abstract class AbstractFactory { abstract function make(AbstractService $s); }
class ConcreteService extends AbstractService { }
class ConcreteFactory extends AbstractFactory { function make(ConcreteService $s) {} }
This LSP violation also raises a Fatal Error:
interface AbstractService { }
interface AbstractFactory { function make(AbstractService $s); }
class ConcreteService implements AbstractService { }
class ConcreteFactory implements AbstractFactory { function make(ConcreteService $s) {} }
While this LSP violation only raises a Warning:
class Service { }
class Factory { function make(Service $s) {} }
class MyService extends Service { }
class MyFactory extends Factory { function make(MyService $s) {} }
Why? Shouldn't they all be fatal since they're all contravariant?
In the first case, it is a fatal error because PHP requires you to be compatible with a parent abstract class:
When inheriting from an abstract class... signatures of the methods must match.
The same is true in the second case:
The class implementing the interface must use the exact same method signatures as are defined in the interface. Not doing so will result in a fatal error.
In the third case, you extend a normal PHP class, not abstract. PHP allows you to change the signature, albeit with a warning.
It obviously isn't a good practice, and does violate LSP as you point out. Just one of the many ways PHP gives you sharp objects, and lets you hurt yourself if you aren't careful. =)
If you want LSP enforced, you need to use an interface, abstract, or make your method final
in the parent class.
Here's an example of final
: https://3v4l.org/s42XG
In May 2019, the LSP errors RFC updated the language. As of PHP 8, the engine will always generate a fatal error for incompatible method signatures.
Before this change, a derived class could change a signature willy-nilly, ignore the error, and move on. No more: classes, just like abstract class
and interface
must abide by LSP.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With