用子接口覆盖方法参数作为新参数
我不知道为什么这个代码不能在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
接受Engine
types的一个参数,但是子WaterCar::setEngine
接受HydroEngine
types的参数。 即使HydroEngine
是Engine
一个子types,它仍然是一个不同的types。
当一个Foo implements WaterCar
类Foo implements WaterCar
,这个类也是instanceof Car
一个instanceof Car
。 但是Foo::setEngine
接受一个HydroEngine
,但是不接受一个Engine
。 所以Foo::setEngine
据说implements Car
,但不接受Engine
types的参数。 这打破了Liskov替代原则 。 您不能更改子类别接口中的参数types。
inheritance的关键字是显式extends
。 一个子类和父类完全一样 ,可能更多 。 它不能less于父母。 由于HydroEngine
是Engine
的专用子types,因此这意味着WaterCar
比Car
,因为它只接受更窄的Engine
types。 例如:
function (Car $car) { $engine = new EngineImplementation; $car->setEngine($engine); }
如果你在WaterCar
传入,上面的代码会WaterCar
,因为它不接受Engine
。
我认为方法签名仍然需要完全一样,因为在编译时,如果HydroEngine是一个引擎,它不会工作。
interface WaterCar extends Car { function setEngine(Engine $engine); }