以下程序可以考虑双重发送示例吗?

时间:2017-08-26 13:42:50

标签: java polymorphism double-dispatch

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());
     }
}

上述程序的输出是:

在市场上搜索产品。

在店内搜索手机。

所以,输出意味着调用market.buy(new Product());和shop.buy(new Mobile());通过调用它的对象的引用和传递给它的参数来解析它。因此,如果它同时使用两个函数来调度函数调用,我们可以将其称为双重调度。或者我是否误解了双重调度一词?

1 个答案:

答案 0 :(得分:0)

什么是双重调度?

definition,双重发送是

  

将函数调用分派给不同的具体的机制   函数取决于所涉及的两个对象的运行时类型   电话。

您的调度如何运作?

你有两个对象:

  • 类型Market之一(或Shop等派生类型);
  • 类型Product之一(或Mobile等派生类型)。

您正在使用动态,单一调度来调用正确的buy()方法,具体取决于调用该方法的对象的动态类型:

market.buy(...);  // invokes the Market version of buy()
shop.buy(...);    // invokes the Shop version of buy()

您正在使用重载根据方法的参数选择buy()方法的正确变体:

public void buy(Product product)   // depends on argument's type
public void buy(Mobile mobile)     //    "             "

这是动态调度吗?

不幸的是,用于选择重载函数的参数类型不是运行时参数类型,而是编译时静态类型。

试一试(online demo):

Product p1 = new Product(); 
Product p2 = new Mobile();    
shop.buy(p1);
shop.buy(p2);
p1 = p2;
shop.buy(p1);

这将导致:

Search a product in shop
Search a product in shop
Search a product in shop

因此,代码的行为仅取决于对象的一种运行时类型而不是两种运行时类型,不是真正的双重调度

如何实现动态调度?

您可以使用使用重载和覆盖的弹跳方法,以便在两个对象中组合动态分派:

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 !!
    }
}

然后你打电话:

shop.buy(p1);

将根据shop的实际类型(例如ShopMarket)进行动态调度。这将使用重载来调用权限buy(),该权限是根据动态类型p1选择的。

Online demo here

另一种更复杂的方法可能是使用将类型组合与特定可调用关联的映射。然后,您的代码将使用反射来确定参数的动态类型,以便找到要调用的正确可调用对象。这种方法也可以用于multiple dispatch