What's a double dispatch ?
By definition, the double dispatch is a
mechanism that dispatches a function call to different concrete
functions depending on the runtime types of two objects involved in
the call.
How does your dispatch work ?
You have two objects:
- one of type
Market
(or a derived type such as Shop
);
- one of type
Product
(or a derived type such as Mobile
).
You are using a dynamic, single dispatch to call the correct buy()
method, depending on the dynamic type of the object invoking the method:
market.buy(...); // invokes the Market version of buy()
shop.buy(...); // invokes the Shop version of buy()
You are using overloading to select the right variant of the buy()
method, based on the argument of the method:
public void buy(Product product) // depends on argument's type
public void buy(Mobile mobile) // " "
Is this dynamic dispatch ?
Unfortunately the argument type used for selecting the overloaded function is not the runtime argument type, but the compile-time static type.
Try for example (online demo):
Product p1 = new Product();
Product p2 = new Mobile();
shop.buy(p1);
shop.buy(p2);
p1 = p2;
shop.buy(p1);
This will result in:
Search a product in shop
Search a product in shop
Search a product in shop
So, the behavior of your code depends only on one run-time type of an object and not of two run-time types, it is not a true double dispatch.
How to achieve dynamic dispatch ?
You could use a bouncing approach that uses overload and override in order to combine a dynamic dispatch in both objects :
class Product
{
public void buy(Market m)
{
System.out.println("Search a product in market");
}
public void buy(Shop s)
{
System.out.println("Search a product in shop");
}
}
class Mobile extends Product
{
... // implement the Mobile version of the two functions
}
class Market
{
public void buy(Product product)
{
product.buy (this); // this use overload, but is not seen by caller
}
}
class Shop extends Market
{
public void buy(Product product)
{
product.buy (this); // attention: this has another type here !!
}
}
WHen you then call:
shop.buy(p1);
there will be a dynamic dispatch based on the real type of shop
(e.g. Shop
or Market
). This will use an overload to invoke the right buy()
, that is chosen based on the dynamic type of p1
.
Online demo here
Another more sophisticated way could be the use of a map that associates the combination of types to a specific callable. Your code would then use reflection to determine the dynamic type of the arguments, in order to find the right callable to be invoked. This kind of approach can also be used for multiple dispatch.