FL0Nn
FL0Nn

Reputation: 53

How to use a Double Dispatch with overload in JAVA?

I'm trying to create a double dispatch in JAVA to use overloaded methods.

public abstract class ComposantOrdi {
    protected void equiv(ComposantOrdi c){
        Equivalence.equiv(this, c);
    }
}

public class Montage extends ComposantOrdi{
    protected void equiv(Montage montage){
        Equivalence.equiv(this, montage);
    }
}

public class Equivalence {
    public static void equiv(Montage m, ComposantOrdi c){
        System.out.println("Montage - ComposantOrdi");
    }

    public static void equiv(Montage m, Montage c){
        System.out.println("Montage - Montage");
    }

    public static void equiv(ComposantOrdi m, ComposantOrdi c){
        System.out.println("ComposantOrdi - ComposantOrdi");
    }
}

For the example i create two objects

Montage m2 = new Montage();
ComposantOrdi m3 = new Montage();

m3.equiv(m2);
m3.equiv(m3);
m3.equiv((Montage)m3);

The result is :

ComposantOrdi - ComposantOrdi
ComposantOrdi - ComposantOrdi
ComposantOrdi - ComposantOrdi

But i would like to use overloaded method from Montage class and get something like this :

Montage - Montage
Montage - Montage
Montage - Montage

I probably didn't understand the double dispatch but could you tell me what I'm doing wrong please?

Upvotes: 2

Views: 5722

Answers (2)

Janis
Janis

Reputation: 1050

what You are doing in your code is a single dispatch (not a double dispatch – explanation below) because only one concrete sub type evaluated at runtime is affecting the result (object wich passes itself as this).

In addition ComposantOrdi and Montage provide different methods (check the parameters: ComposantOrdi gets ComposantOrdi while Montage gets Montage). If you call the superclass' equiv method there is no way to get a result like Montage - Montage because every passed Montage is implicitly casted to a ComposantOrdi. Like this calling superclass' method the second part of your result cannot be anything else the ComposantOrdi.

Furthermore if you call the superclass' method the keyword this in

Equivalence.equiv(this, c);

is triggered by the superclass which means even if the object is a Montage it passes itself as ComposantOrdi.

So: Calling the superclass' method can only produce the output ComposantOrdi - ComposantOrdi.

For an output like Montage - Montage you need to call the sub class' method equiv which means:

  • you need to reference the receiver of the equiv call as Montage (see m2 in your main, not m3)
  • you have to pass in a Montage object

Because then the keyword this is triggered in Montage the first part of the output must be Montage. The second part is also Montage because Java does not implicitly cast objects if not neccessary. Thats why the overloaded method with to Montages as Parameters is selected.

So: Calling the sub class' method can only produce the output Montage - Montage.

The mixed version of the Equivalence's equiv method is never called.


EXPLAINING THE DOUBLE DISPATCH MECHANISM:

I think there is a fundamental misunderstanding of the double dispatch mechanism. So let me explain it. I will start explaining a single dispatch before moving on to the double dispatch mechanism.

SINGLE DISPATCH: A Single dispatch means you call a method of an object and the performed behaviour (the result of the method call) depends on the concrete type of the object. Generally this is called polymorphism and is implemented using abstract methods or method overriding.

Assumed you have a class system according to the picture below. The Client holds a list of Shapes. To paint all of them it loops through the list and calls paint on each Shape. While a the class Triangle paints a triangle on the screen a Square paints a square. By not considering of which concrete sub type the Shapes are, the performed behaviour is determined at runtime.

In other words the result of the paint method's call depends on the concrete sub type of the derivatives of the Shape interface. The call of the paint method is a single dispatch because there is only one concrete subtype which determines the performed behaviour at runtime.

enter image description here

DOUBLE DISPATCH: Using the double dispatch mechanism the performed behaviour is affected by two concrete sub types at runtime. Like this you span a behaviour matrix which is evaluated dynamically.

If you modify the class system according to the picture below the paint mechanism triggered by the client is dependent on two objects – Shape and a Painter. The client calls the paint method and injects its Painter. Then the Shape passes itself as this in one of the overloaded methods of the Painter.

Like this the Client triggers the paint mechanism without knowing what kind of shape in what color is painted. If for example its painter is a GreenPainter and the Shape is a Triangle then a green triangle appears on the screen.

In this example the double dispatch mechanism is triggered by the call of the Shapes' paint method.

You should have a look at the visitor pattern which uses the double dispatch mechanism.

enter image description here enter image description here

Upvotes: 13

Nate Schreiner
Nate Schreiner

Reputation: 849

General JVMs only use single dispatch: the runtime type is only considered for the receiver object; for the method's parameters, the static type is considered.

If you want multiple dispatch for your parameters, and you want to stick with Java, take a look at MultiJava

If your goal is to stick with plain, vanilla java, read up on other design patterns such as, Strategy, Visitor, Observer. These can often solve the same problems as multiple dispatch

Upvotes: 1

Related Questions