15

我不明白为什么这段代码在 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)

4

2 回答 2

25

确实违反了 SOLID规则。您声明Car::setEngine接受一个类型的参数Engine,但孩子WaterCar::setEngine接受一个类型的参数HydroEngine。即使HydroEngine是 的子类型Engine,它仍然是不同的类型。

当一个类Foo implements WaterCar时,这个类也是一个instanceof Car。但Foo::setEngine接受 a HydroEngine,但不接受 a Engine。所以Foo::setEngine据说implements Car,但不接受类型的参数Engine。这打破了里氏替换原则。您不能更改子类接口中的参数类型,句号。

继承的关键字是明确的extends。子类与父类完全相同,甚至可能更多。它不能做得比父母少。由于HydroEngine是 的特殊子类型,这Engine意味着 a比 a,因为它只接受 的更窄的子类型。例如:WaterCarCarEngine

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

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

于 2013-10-17T14:17:31.297 回答
1

我认为方法签名仍然需要完全相同,因为在编译时,如果 HydroEngine 是一个引擎,它就不起作用。

interface WaterCar extends Car {
    function setEngine(Engine $engine);
}
于 2013-10-17T14:16:00.507 回答