Can the below program be considered double dispatch example?

68 views Asked by At
class Product
{
}

class Mobile extends Product
{
}

class Market
{
    public void buy(Product product)
    {
        System.out.println("Search a product in market");
    }

    public void buy(Mobile mobile)
    {
        System.out.println("Search a mobile in market");
    }
}

class Shop extends Market
{

    public void buy(Product product)
    {
        System.out.println("Search a product in shop");
    }

    public void buy(Mobile mobile)
    {
        System.out.println("Search a mobile in shop.");
    }
}

public class DoubleDispatchExample 
{

    public static void main(String[] args)
    {
        Market market = new Market();
        Market shop = new Shop();

        market.buy(new Product());
        shop.buy(new Mobile());
     }
}

The output of the above program is :

Search a product in market.

Search a mobile in shop.

So, the output imply that the calls market.buy(new Product()); and shop.buy(new Mobile()); are resolved by both the reference of the object calling it and the parameter passed to it. So if it is using both the things to dispatch a function call, can we call it a double dispatch. Or am I misinterpreting the term double dispatch?

1

There are 1 answers

0
Christophe On

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.