Я не могу понять, почему этот код не работает в 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); }