Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override method parameter with child interface as a new parameter

Tags:

oop

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);
}

?>

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)

like image 339
pleerock Avatar asked Oct 17 '13 14:10

pleerock


People also ask

Can interface override parent interface method?

Although you cannot override the method in C#, what an XML comment does is simply produce an entry in the accompanying XML file. Tools that interpret these comments may or may not do the right thing if you manually insert the documentation for the "new" methods.

Do we need to override all methods of interface?

Yes, it is mandatory to implement all the methods in a class that implements an interface until and unless that class is declared as an abstract class.

Can we override parameters in Java?

The ability of a subclass to override a method allows a class to inherit from a superclass whose behavior is "close enough" and then to modify behavior as needed. The overriding method has the same name, number and type of parameters, and return type as the method that it overrides.

Can we override interface methods in Java?

It is not mandatory to override the default method in Java. If we are using Only one interface in a Program then at a time we are using only a single default method and at that time Overriding is not required as shown in the below program: Java.


1 Answers

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.

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.

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);
}

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

like image 50
deceze Avatar answered Sep 19 '22 13:09

deceze