Переопределите параметр метода с помощью дочернего интерфейса в качестве нового параметра


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

 12
Author: pleerock, 2013-10-17

2 answers

Это действительно нарушает ТВЕРДЫЕ правила. Вы объявляете 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, потому что он не принимает Engine.

 20
Author: deceze, 2013-10-17 14:29:40

Я думаю, что сигнатура метода все еще должна быть точно такой же, потому что во время компиляции не получается, является ли HydroEngine двигателем.

interface WaterCar extends Car {
    function setEngine(Engine $engine);
}
 1
Author: BadHorsie, 2013-10-17 14:16:00