用子接口覆盖方法参数作为新参数

我不知道为什么这个代码不能在PHP中工作?

<?php interface Engine { function run(); } interface HydroEngine extends Engine { function run(); } interface Car { function setEngine(Engine $engine); } interface WaterCar extends Car { function setEngine(HydroEngine $engine); } ?> 

它似乎没有违反任何OOP规则,但为什么它给了我一个错误?

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

确实打破了SOLID规则。 您声明Car::setEngine接受Enginetypes的一个参数,但是子WaterCar::setEngine接受HydroEnginetypes的参数。 即使HydroEngineEngine一个子types,它仍然是一个不同的types。

当一个Foo implements WaterCarFoo implements WaterCar ,这个类也是instanceof Car一个instanceof Car 。 但是Foo::setEngine接受一个HydroEngine ,但是不接受一个Engine 。 所以Foo::setEngine据说implements Car ,但不接受Enginetypes的参数。 这打破了Liskov替代原则 。 您不能更改子类别接口中的参数types。

inheritance的关键字是显式extends 。 一个子类和父类完全一样 ,可能更多 。 它不能less于父母。 由于HydroEngineEngine的专用子types,因此这意味着WaterCarCar ,因为它只接受更窄的Enginetypes。 例如:

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

如果你在WaterCar传入,上面的代码会WaterCar ,因为它不接受Engine

我认为方法签名仍然需要完全一样,因为在编译时,如果HydroEngine是一个引擎,它不会工作。

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