Why are LSP violations in PHP sometimes fatal, and sometimes warnings?

自闭症网瘾萝莉.ら 提交于 2019-12-23 08:50:22

问题


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?


回答1:


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




回答2:


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.



来源:https://stackoverflow.com/questions/37889466/why-are-lsp-violations-in-php-sometimes-fatal-and-sometimes-warnings

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!