Override method parameter with child interface as a new parameter
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
.
Override method so that a parameter requires a subclass
Yes, you make the interface itself actually take the generic parameter:
public interface MyInterface<T extends MyAbstract> {
void someMethod(T param);
}
Then you can limit it where used:
public class AnotherClass<T extends A> implements MyInterface<T> {
@Override
public void someMethod(T param) {}
}
Or:
public class AnotherClass implements MyInterface<A> {
@Override
public void someMethod(A param) {}
}
In Java, how to let child class decide of which type parameter class use as overridden method argument?
Make your base class generic (with generic type T), and make show()
accept a Consumer<T>
(or a Consumer<? super T>
. Make the subclass extend BaseClass<Protection>
.
class BaseClass<T> {
public void show(Consumer<T> validationHandler) { // or Consumer<? super T>
}
}
class SubClass extends BaseClass<Protection> {
@Override
public void show(Consumer<Protection> validationHandler) { // or Consumer<? super Protection>
super.show(validationHandler);
}
}
class Protection {}
How to override parameter defined in interface method with richer type?
You were close, but you need the class generic, not just the method:
public abstract class Manager<T> where T : TennisPlayer
{
protected abstract bool ScheduleFriendlies(T player);
}
You could then use:
public class RafaelNadalManager : Manager<RafaelNadal>
{
protected override bool ScheduleFriendlies(RafaelNadal player)
{}
}
Why does java allow for overriding methods with subclass return types but not subclass parameters?
When parameters allow doing this, they are called contravariant parameters. When you do it with return types, they are called covariant return types. Java supports covariant return types but not contravariant parameters.
That would change the method signature and it will no longer be an override. Return types are not part of the method signature but the type and the number of parameters of the method are part of the signature, hence this would interfere with overloading.
Moreover, if Java allowed you to do that, that would cause unexpected behavior in some cases and break runtime polymorphism with virtual methods because you are narrowing down what the method could accept.
Imagine a scenario where some code or an API only exposes the base class to you. You call someMethod()
to receive a person:
public Person someMethod()
{
Child child = new Child();
return child;
}
This is how it would look like at the calling site:
Person receivedPerson = someMethod();
Person myPerson = new Person();
Person result = receivedPerson.getPerson(myPerson); // This will fail
Here, the caller does not know that someMethod()
has actually returned a Child
instead of a Person
. I would think the Person
class has a method called getPerson()
accepting an object of type Person
and therefore, I can call receivedPerson.getPerson(myPerson)
. But, as the derived type Child
which you don't even know about has changed the parameter type of getPerson()
to Child
, it will not be able to accept myPerson
because you cannot convert an object of the base class to an object of a derived class.
This will never happen with covariant return types because if a method returns a more specific type, say Child
instead of Person
, it can be easily stored in a Person
variable and child will always have all the state and behavior as that of its parent.
Related Topics
How to Implement a Web Scraper in PHP
Display Numbers With Ordinal Suffix in PHP
PHP Get All Subdirectories of a Given Directory
How to Remove the Querystring and Get Only the Url
How to Insert Multiple Rows from a Single Query Using Eloquent/Fluent
How to Include Code into a PHP Class
Remove Script Tag from HTML Content
PHP Array to Json Array Using Json_Encode();
Disable Warnings When Loading Non-well-formed HTML by Domdocument (PHP)
Trying to Get Property of Non-Object - Laravel 5
Unformat Money When Parsing in PHP
How to Hide .PHP Extension in .Htaccess
How Are Echo and Print Different in PHP
How to Get Single Value from This Multi-dimensional PHP Array