Reputation: 53
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
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:
equiv
call as Montage
(see m2
in your main, not m3
)Montage
objectBecause 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.
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.
Upvotes: 13
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