gpt4 book ai didi

java - 如何在JAVA中使用带有重载的Double Dispatch?

转载 作者:行者123 更新时间:2023-11-29 06:50:59 25 4
gpt4 key购买 nike

我正在尝试在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


我可能不理解双重派遣,但是请您告诉我我做错了什么吗?

最佳答案

您在代码中执行的操作是单次调度(而不是双重调度-下文说明),因为在运行时仅评估一种具体的子类型会影响结果(对象本身以this的形式传递)。

另外,ComposantOrdiMontage提供了不同的方法(检查参数:ComposantOrdi获取ComposantOrdi,而Montage获取Montage)。如果调用超类的equiv方法,则无法获得像Montage-Montage这样的结果,因为每个传递的Montage都隐式转换为ComposantOrdi。像这种调用超类的方法一样,结果的第二部分不能是ComposantOrdi。

此外,如果您调用超类的方法中的关键字this


  Equivalence.equiv(this,c);


由超类触发,这意味着即使对象是Montage,它也将自己作为ComposantOrdi传递。

因此:调用超类的方法只能产生输出ComposantOrdi-ComposantOrdi。

对于像Montage-Montage这样的输出,您需要调用子类的方法equiv,这意味着:


您需要将equiv呼叫的接收方引用为Montage(请参见主目录中的m2,而不是m3
您必须传递Montage对象


因为然后在this中触发了关键字Montage,所以输出的第一部分必须是Montage。第二部分也是Montage,因为Java在不需要时不会隐式转换对象。这就是为什么选择以Montages作为参数的重载方法的原因。

因此:调用子类的方法只能产生输出Montage-Montage。

永远不会调用等价equiv方法的混合版本。



说明双重分配机制:

我认为双重派遣机制存在根本性的误解。所以让我解释一下。在继续介绍双调度机制之前,我将开始解释单调度。

单次派遣:
单一调度意味着您调用对象的方法,并且已执行的行为(方法调用的结果)取决于对象的具体类型。通常,这称为多态性,是使用抽象方法或方法重写实现的。

假设您根据下图有一个班级系统。 Client包含Shapes的列表。要绘制所有这些内容,它将在列表中循环并在每个paint上调用Shape。类Triangle在屏幕上绘制一个三角形,而Square在屏幕上绘制一个正方形。通过不考虑Shapes是哪种具体子类型,可以在运行时确定执行的行为。

换句话说,paint方法的调用结果取决于Shape接口的派生类的具体子类型。由于只有一个具体的子类型可以确定运行时所执行的行为,所以paint方法的调用是单个调度。

enter image description here

双重调度:使用双重调度机制,执行的行为在运行时会受到两种具体子类型的影响。像这样,您将跨越一个行为矩阵,并对其进行动态评估。

如果根据下面的图片修改类系统,则客户端触发的绘制机制取决于两个对象-ShapePainter。客户端调用paint方法并注入其Painter。然后,Shapethis的重载方法之一中将自身作为Painter传递。

这样,Client会触发绘制机制,而无需知道绘制哪种颜色的形状。例如,如果其画家是GreenPainter,而ShapeTriangle,则屏幕上会出现一个绿色三角形。

在此示例中,双重分配机制由Shapes'paint方法的调用触发。

您应该看看使用双重分配机制的访客模式。

enter image description here
enter image description here

关于java - 如何在JAVA中使用带有重载的Double Dispatch?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48213295/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com