Java method overloading + double dispatch
Solution 1:
The JLS states in §8.4.9 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).
So in your case:
- The method argument (
this
) is of compile-time typeParent
, and so the methodprint(Parent)
is invoked. - If the
Worker
class was subclassed and the subclass would override that method, and theworker
instance was of that subclass, then the overridden method would be invoked.
Double dispatch does not exist in Java. You have to simulate it, e.g. by using the Visitor Pattern. In this pattern, basically, each subclass implements an accept
method and calls the visitor with this
as argument, and this
has as compile-time type that subclass, so the desired method overloading is used.
Solution 2:
The reason is that doJob
is implemented in Parent
and not overloaded in Child
. It passes this
to the worker's print
methos, because this
is of the type Parent
the method Worker::print(Parent)
will be called.
In order to have Worker::print(Parent)
called you needto overload doJob
in Child
:
public static class Child extends Parent {
public void doJob(Worker worker) {
System.out.println("from Child: this is " + this.getClass().getName());
worker.print(this);
}
}
In the code above this.getClass()
in Child
is equivalent to Child.class
.