Reemplazar el parámetro de método con la interfaz hija como un nuevo parámetro

No puedo entender por qué este código no funciona en PHP.

 

Parece que no rompe ninguna regla de OOP, pero ¿por qué me da un error?

Fatal error: Declaration of WaterCar::setEngine() must be compatible with Car::setEngine(Engine $engine)

Rompe reglas SÓLIDAS . Usted declara que Car::setEngine acepta un parámetro de tipo Engine , pero el niño WaterCar::setEngine acepta un parámetro de tipo HydroEngine . Incluso si HydroEngine es un subtipo de Engine , sigue siendo un tipo diferente.

Cuando una clase Foo implements WaterCar , también es cierto que esta clase es una instanceof Car . Pero Foo::setEngine acepta un HydroEngine , pero no acepta un Engine . Así que Foo::setEngine supuestamente implements Car , pero no acepta un parámetro de tipo Engine . Lo cual rompe el principio de sustitución de Liskov . No puede cambiar el tipo de parámetros en las interfaces subclasificadas, punto.

La palabra clave para herencia se extends explícitamente. Una subclase hace exactamente lo mismo que la clase padre y posiblemente más . No puede hacer menos que el padre. Dado que HydroEngine es un subtipo especializado de Engine , esto significaría que un WaterCar hace menos que un Car , ya que solo acepta un subtipo más estrecho de Engine . P.ej:

 function (Car $car) { $engine = new EngineImplementation; $car->setEngine($engine); } 

El código anterior implosionaría si pasó en un WaterCar , porque no acepta un Engine .

Creo que la firma del método todavía tiene que ser exactamente igual porque en el tiempo de comstackción no funciona si HydroEngine es un motor.

 interface WaterCar extends Car { function setEngine(Engine $engine); }