Pregunta ¿Por qué las violaciones de LSP en PHP a veces son fatales y, a veces, las advertencias?


Esta violación LSP plantea un error fatal:

abstract class AbstractService { }
abstract class AbstractFactory { abstract function make(AbstractService $s); }
class ConcreteService extends AbstractService { }
class ConcreteFactory extends AbstractFactory { function make(ConcreteService $s) {} }

Esta violación LSP también plantea un error fatal:

interface AbstractService { }
interface AbstractFactory { function make(AbstractService $s); }
class ConcreteService implements AbstractService { }
class ConcreteFactory implements AbstractFactory { function make(ConcreteService $s) {} }

Mientras esta violación LSP solamente plantea una advertencia:

class Service { }
class Factory { function make(Service $s) {} }
class MyService extends Service { }
class MyFactory extends Factory { function make(MyService $s) {} }

¿Por qué? ¿No deberían todos ser fatales ya que todos son contravariantes?


7
2018-06-17 19:56


origen


Respuestas:


En el primer caso, es un error fatal porque PHP requiere que seas compatible con un padre abstracto clase:

Al heredar de una clase abstracta ... las firmas de los métodos deben coincidir.

los lo mismo es cierto en el segundo caso:

La clase que implementa la interfaz debe usar las mismas firmas de método que se definen en la interfaz. No hacerlo ocasionará un error fatal.

En el tercer caso, extiendes una clase PHP normal, no abstracta. PHP le permite cambiar la firma, aunque con una advertencia.

Obviamente no es una buena práctica, y viola LSP como usted señala. Es solo una de las muchas maneras en que PHP te ofrece objetos filosos y te permite hacerte daño si no tienes cuidado. =)

Si desea aplicar LSP, debe usar una interfaz, resumen o hacer su método final en la clase de padres

Aquí hay un ejemplo de final: https://3v4l.org/s42XG


8
2018-06-17 19:59