用子接口作为新参数覆盖方法参数

问题描述:

我不知道为什么此代码在PHP中不起作用?

I cant figure out why this code does not work in 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规则,但是为什么会给我一个错误?

It seems it does not break any OOP rules, but why it gives me an error?

Fatal error: Declaration of WaterCar::setEngine() must be compatible with Car::setEngine(Engine $engine)

确实中断了 SOLID 规则.您声明Car::setEngine接受类型为Engine的一个参数,但是子级WaterCar::setEngine接受类型为HydroEngine的参数.即使HydroEngineEngine的子类型,它仍然是不同的类型.

It does break SOLID rules. You declare Car::setEngine to accept one parameter of type Engine, but the child WaterCar::setEngine accepts a parameter of type HydroEngine. Even if HydroEngine is a subtype of Engine, it's still a different type.

当一个类为Foo implements WaterCar时,该类为instanceof Car也是正确的.但是Foo::setEngine接受HydroEngine,但不接受Engine.因此,Foo::setEngine应该是implements Car,但不接受Engine类型的参数.这违反了 Liskov替代原则.您不能在子类化接口中更改参数类型,即周期.

When a class Foo implements WaterCar, it is also true that this class is an instanceof Car. But Foo::setEngine accepts a HydroEngine, but does not accept an Engine. So Foo::setEngine supposedly implements Car, yet does not accept a parameter of type Engine. Which breaks the Liskov substitution principle. You cannot change the type of parameters in subclassed interfaces, period.

用于继承的关键字显式为 extends .子类与父类确实完全相同,甚至可能与父类完全相同.它不能比父对象做得.由于HydroEngineEngine的特殊子类型,因此这意味着WaterCarCar更少,因为它只接受更窄的Engine子类型.例如:

The keyword for inheritance is explicitly extends. A subclass does exactly the same as the parent class and possibly more. It cannot do less than the parent. Since HydroEngine is a specialized subtype of Engine, this would mean a WaterCar does less than a Car, since it only accepts a more narrow subtype of Engine. E.g.:

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

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

The above code would implode if you passed in a WaterCar, because it does not accept an Engine.