使用子接口作为新参数覆盖方法参数 [英] Override method parameter with child interface as a new parameter
问题描述
我不明白为什么这段代码在 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?
致命错误:WaterCar::setEngine() 的声明必须与 Car::setEngine(Engine $engine) 兼容
推荐答案
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实现了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
.子类与父类完全相同,并且可能更多.它不能比父级少.由于HydroEngine
是Engine
的一个特殊子类型,这意味着WaterCar
比Car
,因为它只接受更窄的 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
.
这篇关于使用子接口作为新参数覆盖方法参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!