【发布时间】:2017-02-27 14:58:58
【问题描述】:
在讲座中,我们看到了这段代码,并告诉我们它会创建双重调度,但为什么它没有创建无限循环?
如果 c3po.greet(c4po);从 TranslationRobot 调用 TranslationRobot 方法
为什么 c5po.greet(c4po);调用 CarrierRobot 中的 AbstractRobot 方法而不是 TranslationRobot 方法,然后不调用 TranslationRobot 中的 AbstractRobot 方法,然后调用 CarrierRobot 中的 Abstract 方法等等?
什么决定了它是否调用 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.'
【问题讨论】:
-
方法名的重载选择是在编译时根据方法参数的static类型进行的。在 Java 中实现双重分派时,这可能是最重要的一点。
-
我不同意这是一个重复的问题,另一个有一个父类,从该类中调用该方法并询问为什么“this”指的是父类而不是子类。而在这里我要问的是为什么在同一个类中选择一种方法而不是另一种方法,以及为什么论点是抽象的或具体的
-
虽然欺骗目标在某些细节上有所不同,但本质上是同一个问题:双重调度中特定的重载方法如何绑定到方法调用?接受的对欺骗目标的回答很好地解决了这个问题,既回答了那个版本的问题,也回答了这个问题。
-
运行的方法是您调用其方法的对象的运行时类型中的方法。
c3po.greet是来自TranslationRobot的方法,因为那是对象的类型。 ` c5po.greet(c4po);` 不“调用 CarrierRobot 中的 AbstractRobot 方法”,它调用CarrierRobot#greet。因为那是对象的类型。它将如何从TranslationRobot调用方法?这不是对象的类型,也不是其变量的类型。那么,你所描述的这种循环怎么会出现呢?
标签: java double-dispatch