Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java method overloading + double dispatch

Can anybody explain in detail the reason the overloaded method print(Parent parent) is invoked when working with Child instance in my test piece of code?

Any pecularities of virtual methods or methods overloading/resolution in Java involved here? Any direct reference to Java Lang Spec? Which term describes this behaviour? Thanks a lot.

public class InheritancePlay {

    public static class Parent {        
        public void doJob(Worker worker) {
            System.out.println("this is " + this.getClass().getName());

            worker.print(this);
        }
    }

    public static class Child extends Parent {
    }

    public static class Worker {
        public void print(Parent parent) {
            System.out.println("Why this method resolution happens?");
        }

        public void print(Child child) {
            System.out.println("This is not called");
        }
    }

    public static void main(String[] args) {
        Child child = new Child();
        Worker worker = new Worker();

        child.doJob(worker);
    }
}
like image 589
Max Avatar asked May 08 '10 13:05

Max


People also ask

What is double dispatching in Java?

Double dispatch is a technical term to describe the process of choosing the method to invoke based both on receiver and argument types. A lot of developers often confuse double dispatch with Strategy Pattern. Java doesn't support double dispatch, but there are techniques we can employ to overcome this limitation.

Is overloading multiple dispatch?

Multiple dispatch is not (always) the same as function overloading, although they do bear some similarities. And Java does not support multiple dispatch.

Does Java support multiple dispatch?

In Java, there's no direct support for multiple dispatch. However you can emulate multiple dispatch by using several layers of single dispatch combined with overloading.

Why is it called double dispatch?

In software engineering, double dispatch is a special form of multiple dispatch, and a mechanism that dispatches a function call to different concrete functions depending on the runtime types of two objects involved in the call.


2 Answers

The JLS states in §8.4.9 Overloading:

  1. 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).
  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:

  1. The method argument (this) is of compile-time type Parent, and so the method print(Parent) is invoked.
  2. If the Worker class was subclassed and the subclass would override that method, and the worker 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.

like image 137
Christian Semrau Avatar answered Oct 20 '22 06:10

Christian Semrau


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.

like image 39
rsp Avatar answered Oct 20 '22 05:10

rsp