user1589188 user1589188 - 1 month ago 11
Java Question

Java polymorphism dilemma

Given the following implementations:

public class MyClass {
public void myFunc(MyClass o) {
System.out.println("Method:MyClass#myFunc(MyClass)");
}
}

public class MyExtClass extends MyClass {
public void myFunc(MyClass o) {
System.out.println("Method:MyExtClass#myFunc(MyClass)");
}
public void myFunc(MyExtClass o) {
System.out.println("Method:MyExtClass#myFunc(MyExtClass)");
}
}

public class Main {
public static void main(String[] args) {
MyClass c = new MyExtClass();
c.myFunc(c);
}
}
Output:
Method:MyExtClass#myFunc(MyClass)


Why if the method in
MyExtClass
was called, meaning c was recognised as
MyExtClass
, but the polymorphic version of
myFunc(MyClass)
was called instead of
myFunc(MyExtClass)
?

If the polymorphic version of method
myFunc(MyClass)
was called, meaning c was recognised as
MyClass
, but the method in
MyExtClass
was called instead of
MyClass
?

Answer

tldr; Run-time subtype polymorphism applies only to the selection of overridden virtual method. Overridden methods must share the same signature. The method myFunc(MyExtClass) is and overload and it does not override myFunc(MyClass).


The type signature of the method is picked at compile-time based on the

  1. compile-time type of the expression used as the target
  2. the method name
  3. and the compile-time types of all the argument expressions.

To the compiler, methods with different parameter types effectively have different names!

In this case the signature of the method that is picked is myFunc(MyClass).

The method MyExtClass#myFunc(MyExtClass) has a different type-signature and is not even a valid method on c which is typed as MyClass; myFunc(MyClassExt) is defined on the MyExtClass subtype of MyClass and thus ((MyClass)c).myFunc(..) will never resolve to it per selection rule #1.


Examples:

MyClass c = new MyExtClass();
MyExtClass e = (MyExtClass)c;
c.myFunc(c);     // matches #myFunc(MyClass)
                 //   calls MyExtClass#myFunc(MyClass) - polymorphic dispatch!
c.myFunc(e);     // matches #myFunc(MyClass)
                 //   calls MyExtClass#myFunc(MyClass) - polymorphic dispatch!
e.myFunc(c);     // matches #myFunc(MyClass)
                 //   calls MyExtClass#myFunc(MyClass)
e.myFunc(e);     // matches #myFunc(MyExtClass) - OVERLOADed method: not override!
                 //   calls MyExtClass#myFunc(MyExtClass)

In all cases the MyExtClass methods were called; however only MyExtClass#myFunc(MyClass) overrides MyClass#myFunc(MyClass).

Comments