Я не могу понять, почему этот код не работает в 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); } ?>
Кажется, он не нарушает правил ООП, но почему это дает мне ошибку?
Fatal error: Declaration of WaterCar::setEngine() must be compatible with Car::setEngine(Engine $engine)
Он нарушает правила SOLID . Вы объявляете Car::setEngine
принимать один параметр типа Engine
, но дочерний WaterCar::setEngine
принимает параметр типа HydroEngine
. Даже если HydroEngine
является подтипом Engine
, он по-прежнему отличается от другого.
Когда класс Foo implements WaterCar
, также верно, что этот класс является instanceof Car
. Но Foo::setEngine
принимает HydroEngine
, но не принимает Engine
. Итак, Foo::setEngine
предположительно implements Car
, но не принимает параметр типа Engine
. Что нарушает принцип замещения Лискова . Вы не можете изменить тип параметров в подклассах интерфейсов, период.
Ключевое слово для наследования явно extends
. Подкласс делает то же самое, что и родительский класс и, возможно, больше . Он не может делать меньше, чем родитель. Поскольку HydroEngine
является специализированным подтипом Engine
, это означает, что WaterCar
делает меньше, чем Car
, поскольку он принимает только более узкий подтип Engine
. Например:
function (Car $car) { $engine = new EngineImplementation; $car->setEngine($engine); }
Вышеупомянутый код будет взрываться, если вы WaterCar
в WaterCar
, потому что он не принимает Engine
.
Я думаю, что подпись метода все равно должна быть точно такой же, потому что во время компиляции это не сработает, если HydroEngine – это Двигатель.
interface WaterCar extends Car { function setEngine(Engine $engine); }