我试图在JAVA中创建一个双分派,以使用重载的方法。
public abstract class ComposantOrdi {
protected void equiv(ComposantOrdi c){
Equivalence.equiv(this, c);
}
}
public class Montage extends ComposantOrdi{
protected void equiv(Montage montage){
Equivalence.equiv(this, montage);
}
}
public class Equivalence {
public static void equiv(Montage m, ComposantOrdi c){
System.out.println("Montage - ComposantOrdi");
}
public static void equiv(Montage m, Montage c){
System.out.println("Montage - Montage");
}
public static void equiv(ComposantOrdi m, ComposantOrdi c){
System.out.println("ComposantOrdi - ComposantOrdi");
}
}对于这个例子,我创建了两个对象
Montage m2 = new Montage();
ComposantOrdi m3 = new Montage();
m3.equiv(m2);
m3.equiv(m3);
m3.equiv((Montage)m3);结果是:
ComposantOrdi - ComposantOrdi
ComposantOrdi - ComposantOrdi
ComposantOrdi - ComposantOrdi但是,我想使用蒙太奇类中的重载方法,并得到如下内容:
Montage - Montage
Montage - Montage
Montage - Montage我可能不明白双重派遣,但是你能告诉我我做错了什么吗?
发布于 2018-01-14 11:23:19
您在代码中所做的是一个单个分派(而不是一个双分派--下面解释),因为在运行时计算的一个具体子类型正在影响结果(对象作为this传递给自己)。
此外,ComposantOrdi和Montage提供了不同的方法(检查参数:ComposantOrdi获取ComposantOrdi,Montage获取Montage)。如果您调用超类的equiv方法,就无法获得像Montage-Mon太奇这样的结果,因为每个传递的Montage都被隐式地传递给ComposantOrdi。就像这个调用超类的方法一样,结果的第二部分不能是其他任何东西-- ComposantOrdi。
此外,如果您将超类的方法称为关键字this
Equivalence.equiv(这个,c);
由超类触发,这意味着即使对象是Montage,它也会将自身传递为ComposantOrdi。
因此:调用超类的方法只能产生输出ComposantOrdi - ComposantOrdi。
对于蒙太奇这样的输出,您需要调用子类的equiv方法,这意味着:
equiv调用的接收方引用为Montage (参见主目录中的m2,而不是m3)Montage对象因为关键字this是在Montage中触发的,所以输出的第一部分必须是蒙太奇。第二部分也是蒙太奇,因为如果没有必要的话,Java不会隐式地转换对象。这就是为什么选择以to Montages作为参数的重载方法的原因。
因此:调用子类的方法只能产生输出蒙太奇-蒙太奇。
等价物的equiv方法的混合版本从未被调用。
解释双重调度机制:
我认为对双重派遣机制有一个根本性的误解。让我来解释一下。在讨论双重调度机制之前,我将开始解释一次调度。
单次分派:单个分派意味着调用对象的方法,执行的行为(方法调用的结果)取决于对象的具体类型。通常,这被称为多态,并使用抽象方法或重写方法实现。
根据下面的图片,假设你有一个班级系统。Client保存一个Shapes列表。为了绘制所有这些代码,它循环遍历列表,并在每个Shape上调用Shape。当一个类Triangle在屏幕上画一个三角形时,一个Square画一个正方形。如果不考虑Shapes的具体子类型,则在运行时确定所执行的行为。
换句话说,油漆方法调用的结果取决于Shape接口的导数的具体子类型。call方法的调用是一个单个分派,因为只有一个具体子类型,它决定运行时执行的行为。

双重分派:使用双分派机制,执行的行为在运行时受到两种具体子类型的影响。就像这样,您跨越了一个动态评估的行为矩阵。
如果您根据下面的图片修改类系统,则由客户端触发的画图机制依赖于两个对象-- Shape和Painter。客户端调用paint方法并注入其Painter。然后,Shape将自己作为this传递到Painter的一个重载方法中。
就像这样,Client触发了画图机制,而不知道用什么颜色绘制的形状。例如,如果它的画家是GreenPainter,而Shape是Triangle,那么屏幕上就会出现一个绿色三角形。
在本例中,双分派机制由Shapes‘paint方法的调用触发。
您应该了解一下使用双分派机制的访问者模式。


发布于 2018-01-11 18:42:34
一般JVM只使用单个调度:运行时类型只考虑接收对象;对于方法的参数,则考虑静态类型。
如果您希望对参数进行多个分派,并且希望继续使用Java,请看一看MultiJava
如果您的目标是坚持使用普通的、普通的java,请阅读其他设计模式,例如,策略、访问者、观察者。它们通常可以解决与多个调度相同的问题。
https://stackoverflow.com/questions/48213295
复制相似问题