Polymorphism does not work in method arguments in Java

I wrote the following code snippet:

class Plane {} class Airbus extends Plane {} public class Main { void fly(Plane p) { System.out.println("I'm in a plane"); } void fly(Airbus a) { System.out.println("I'm in the best Airbus!"); } public static void main(String[] args) { Main m = new Main(); Plane plane = new Plane(); m.fly(plane); Airbus airbus = new Airbus(); m.fly(airbus); Plane planeAirbus = new Airbus(); m.fly(planeAirbus); } } 

And the result:

 I'm in a plane I'm in the best Airbus! I'm in a plane 

No wonder the two first calls are I'm in a plane and I'm in the best Airbus! respectively.

 Plane planeAirbus = new Airbus(); 

The method treats this object as a plane, although the real object is Airbus. Even when I add abstract to class Plane , nothing changes, and the result of the last call is still I'm in a plane

So the question is, why does polymorphism not work in method arguments and calls? Is there any purpose? How it works?

+7
java polymorphism oop
source share
4 answers

The problem here is that Java does not support dynamic binding of method arguments. What you see is a static binding, i.e. The method overload for the call is selected at compile time.

See also: Static Binding and Dynamic Binding

+4
source share

Polymorphism such as method overload is determined at compile time in Java.

This means that Java must infer the type of method parameters from the reference type that they represent, since it has no idea about the type of object that they store at compile time.

We can argue that in this case it is pretty clear that the Plane type reference contains an instance of the Airbus type. However, this is not so simple, since the Airbus instance itself could be a parameter of the method, which could contain any instance of the subclass or the Airbus instance itself.

The only safe bet is not to parse the parent chain and take a reference to its nominal value, which is the actual type of the reference variable. Another way to do this could be by overloading the method in the same way as overriding, and by using the runtime of objects to resolve. I do not know why this was not done in the way that it could lead to overloading the method and overriding a more uniform one.

Below are the links from JLS Overloading

When a method is invoked (§15.12), the number of actual arguments (and any explicit type arguments) and argument compilation time types are used at compile time to determine the signature of the method to be invoked (§15.12.2). If the method to be called is an instance method, the actual method to be called will be determined at runtime using the dynamic method search (§15.12.4).
+2
source share

Reason for output of the following output:

 I'm in a plane I'm in the best Airbus! I'm in a plane 

Because it does overloading, and overloading is a static polymorphism or compile-time polymorphism. When overloaded, a class can have several methods with the same name, but with different types of arguments. In your example, Plane has a type for Plane planeAirbus = new Airbus();

+1
source share

Java overloading is a compile-time polymorphism. So, when you declare planeAirbus as Plane , it will call fly(Plane) .

In fact, the Main class does not need to know how Plane and Airbus can fly. Better than him:

 public interface Flyable{ void fly(); } public Plane implements Flyable{ void fly(){ //do something } } public Airbus implements Flyable{ void fly(){ //do something } } 

And then in the Main class

 public static void main(String[] args) { Flyable plane = new Plane(); plane.fly(plane); Flyable airbus = new Airbus(); airbus.fly(airbus); } 
+1
source share

All Articles