我无法弄清楚为什么这段代码在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)
答案 0 :(得分:23)
它 打破SOLID规则。您声明Car::setEngine
接受Engine
类型的一个参数,但子WaterCar::setEngine
接受类型为HydroEngine
的参数。即使HydroEngine
是Engine
的子类型,它仍然是不同的类型。
当一个班级Foo implements WaterCar
时,这个班级也是instanceof Car
。但Foo::setEngine
接受HydroEngine
,但不接受Engine
。所以Foo::setEngine
应该implements Car
,但不接受Engine
类型的参数。打破了Liskov substitution principle。您无法更改子类接口中的参数类型,周期。
继承的关键字是 extends
。子类与父类完全相同,可能更多。它不能比父母更少。由于HydroEngine
是Engine
的专用子类型,这意味着WaterCar
更少而不是Car
,因为它只接受更窄Engine
的子类型。 E.g:
function (Car $car) {
$engine = new EngineImplementation;
$car->setEngine($engine);
}
如果您传入WaterCar
,则上述代码会崩溃,因为它不接受Engine
。
答案 1 :(得分:1)
我认为方法签名仍然需要完全相同,因为在编译时,如果HydroEngine是Engine,它就无法解决。
interface WaterCar extends Car {
function setEngine(Engine $engine);
}