为什么无限循环不是由Java双重调度引起的?

时间:2017-02-27 14:58:58

标签: java double-dispatch

在讲座中,我们看到了这段代码,并告诉它会创建双重调度,但为什么它不会创建无限循环?

如果是c3po.greet(c4po);从TranslationRobot调用TranslationRobot方法

为什么c5po.greet(c4po);在CarrierRobot中调用AbstractRobot方法而不是TranslationRobot方法,然后不在TranslationRobot中调用AbstractRobot方法,然后在CarrierRobot中调用抽象方法等等?

是什么决定它是否调用AbstractRobot方法?

AbstractRobot.java

abstract class AbstractRobot extends Robot { 
abstract void greet(AbstractRobot other);
abstract void greet(TranslationRobot other);
abstract void greet(CarrierRobot other);
}

CarrierRobot.Java

class CarrierRobot extends AbstractRobot {
...
void greet(TranslationRobot other) {
    talk("'Hello from a TranslationRobot to a CarrierRobot.'"); }
void greet(CarrierRobot other) {
    talk("'Hello from a CarrierRobot to another.'"); }
void greet(AbstractRobot other) {
    other.greet(this); 
}}

TranslationRobot.Java

public class TranslationRobot extends AbstractRobot {
...
void greet(TranslationRobot other) {
    talk("'Hello from a TranslationRobot to another.'"); }
void greet(CarrierRobot other) {
    talk("'Hello from a CarrierRobot to a TranslationRobot.'"); }
void greet(AbstractRobot other) {
    other.greet(this);
} } 

DispatchWorld.Java

class DispatchWorld {
public static void main (String[] args) {
AbstractRobot c3po = new TranslationRobot();
AbstractRobot c4po = new TranslationRobot();
AbstractRobot c5po = new CarrierRobot();
AbstractRobot c6po = new CarrierRobot();
c3po.greet(c4po);
c5po.greet(c4po);
c4po.greet(c5po);
c5po.greet(c6po);
} }

这会产生输出:

Standard Model says 'Hello from a TranslationRobot to another.'
Standard Model says 'Hello from a CarrierRobot to a TranslationRobot.'
Standard Model says 'Hello from a TranslationRobot to a CarrierRobot.'
Standard Model says 'Hello from a CarrierRobot to another.'

1 个答案:

答案 0 :(得分:0)

我认为,如果我们通过删除所有方法重载并改为使用明确的不同名称来重构代码,那么为什么这个有效以及为什么没有无限递归的答案可能会更好地说明:

abstract class Robot
{
    void talk(String msg)
    {
        System.out.println(msg);
    }
}

abstract class AbstractRobot extends Robot
{
    abstract void greet(AbstractRobot other);

    abstract void greetFromTranslationRobot(TranslationRobot other);

    abstract void greetFromCarrierRobot(CarrierRobot other);
}

class CarrierRobot extends AbstractRobot
{
    void greetFromTranslationRobot(TranslationRobot other)
    {
        talk("'Hello from a TranslationRobot to a CarrierRobot.'");
    }

    void greetFromCarrierRobot(CarrierRobot other)
    {
        talk("'Hello from a CarrierRobot to another.'");
    }

    void greet(AbstractRobot other)
    {
        other.greetFromCarrierRobot(this);
    }
}


public class TranslationRobot extends AbstractRobot
{
    void greetFromTranslationRobot(TranslationRobot other)
    {
        talk("'Hello from a TranslationRobot to another.'");
    }

    void greetFromCarrierRobot(CarrierRobot other)
    {
        talk("'Hello from a CarrierRobot to a TranslationRobot.'");
    }

    void greet(AbstractRobot other)
    {
        other.greetFromTranslationRobot(this);
    }
}

从编译器的角度来看,方法void greet(AbstractRobot other)void greet(TranslationRobot other)void greet(CarrierRobot other)是明显不同的方法,我的重命名只是突出显示。

c3po.greet(c4po)之类的调用实际上是对TranslationRobot.greet的调用,它会将其转发到other.greetFromTranslationRobot(this) TranslationRobot.greetFromTranslationRobot,这显然不会导致任何无限递归。< / p>