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::setEnginetype のパラメーターを 1 つ受け入れるように宣言しましEngineたが、子WaterCar::setEngineは type のパラメーターを受け入れますHydroEngineHydroEngineが のサブタイプであってEngineも、別のタイプです。

クラスFoo implements WaterCarの場合、このクラスがinstanceof Car. ただし、Foo::setEngineは受け入れますがHydroEngine、 は受け入れませんEngine。おそらく、Foo::setEngineまだimplements Car型のパラメータを受け入れませんEngine。これは、リスコフの置換原理を破っています。サブクラス化されたインターフェイス、期間のパラメーターのタイプを変更することはできません。

継承のキーワードは明示的extendsです。サブクラスは、親クラスとまったく同じことを行い、場合によってはそれ以上のことを行います。親よりも少ないことはできません。HydroEngineは の特殊なサブタイプであるため、より狭いサブタイプの のみを受け入れるため、これは aがa より少ないEngineことを意味します。例えば:WaterCarCarEngine

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

上記のコードは、 を渡した場合、 をWaterCar受け入れないため内破しますEngine

于 2013-10-17T14:17:31.297 に答える
1

HydroEngine がエンジンである場合、コンパイル時にうまくいかないため、メソッド シグネチャはまったく同じである必要があると思います。

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