Polymorphism doesn't work in method arguments in Java
The problem here is that Java does not support dynamic binding of method arguments. What you see is static binding, i.e. the overload of the method to call is chosen at compile time.
See also: Static Binding and Dynamic Binding
Method overloading type polymorphism is determined at the compile time in Java.
Meaning that Java has to infer type of the method parameters from the reference type they represent, as it has no idea about the type of object they hold at the compile time.
We can argue that it's pretty clear in this case that reference of Plane type holds Airbus type instance. However it's not that simple, as the Airbus instance itself could have been a method parameter, which could hold any subclass instance or Airbus instance itself.
Only safe bet is to not parse through the parent chain and take the reference for it's face value that is actual reference variable type. Another way of doing this could have been by implementing method overloading same as overriding and by using run time binding of objects for resolution. I don't know why it wasn't done this way as it would have made method overloading and overriding more uniform.
Following are the references from JLS Overloading
When a method is invoked (§15.12), the number of actual arguments (and any explicit type arguments) and the compile-time types of the arguments are used, at compile time, to determine the signature of the method that will be invoked (§15.12.2). If the method that is to be invoked is an instance method, the actual method to be invoked will be determined at run time, using dynamic method lookup (§15.12.4).
Java overloading is compile time polymorphism. So, when you declare planeAirbus
as Plane
, it will invoke fly(Plane)
.
In fact, class Main
shouldn't know than Plane
and Airbus
can fly.
Better design of it:
public interface Flyable{
void fly();
}
public Plane implements Flyable{
void fly(){
//do something
}
}
public Airbus implements Flyable{
void fly(){
//do something
}
}
And then in Main
class
public static void main(String[] args) {
Flyable plane = new Plane();
plane.fly();
Flyable airbus = new Airbus();
airbus.fly();
}