首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在JAVA中使用带有重载的双调度?

如何在JAVA中使用带有重载的双调度?
EN

Stack Overflow用户
提问于 2018-01-11 18:02:41
回答 2查看 4.2K关注 0票数 2

我试图在JAVA中创建一个双分派,以使用重载的方法。

代码语言:javascript
复制
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");
    }
}

对于这个例子,我创建了两个对象

代码语言:javascript
复制
Montage m2 = new Montage();
ComposantOrdi m3 = new Montage();

m3.equiv(m2);
m3.equiv(m3);
m3.equiv((Montage)m3);

结果是:

代码语言:javascript
复制
ComposantOrdi - ComposantOrdi
ComposantOrdi - ComposantOrdi
ComposantOrdi - ComposantOrdi

但是,我想使用蒙太奇类中的重载方法,并得到如下内容:

代码语言:javascript
复制
Montage - Montage
Montage - Montage
Montage - Montage

我可能不明白双重派遣,但是你能告诉我我做错了什么吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-01-14 11:23:19

您在代码中所做的是一个单个分派(而不是一个分派--下面解释),因为在运行时计算的一个具体子类型正在影响结果(对象作为this传递给自己)。

此外,ComposantOrdiMontage提供了不同的方法(检查参数:ComposantOrdi获取ComposantOrdiMontage获取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方法的调用是一个单个分派,因为只有一个具体子类型,它决定运行时执行的行为。

双重分派:使用分派机制,执行的行为在运行时受到两种具体子类型的影响。就像这样,您跨越了一个动态评估的行为矩阵。

如果您根据下面的图片修改类系统,则由客户端触发的画图机制依赖于两个对象-- ShapePainter。客户端调用paint方法并注入其Painter。然后,Shape将自己作为this传递到Painter的一个重载方法中。

就像这样,Client触发了画图机制,而不知道用什么颜色绘制的形状。例如,如果它的画家是GreenPainter,而ShapeTriangle,那么屏幕上就会出现一个绿色三角形。

在本例中,双分派机制由Shapespaint方法的调用触发。

您应该了解一下使用双分派机制的访问者模式

票数 11
EN

Stack Overflow用户

发布于 2018-01-11 18:42:34

一般JVM只使用单个调度:运行时类型只考虑接收对象;对于方法的参数,则考虑静态类型。

如果您希望对参数进行多个分派,并且希望继续使用Java,请看一看MultiJava

如果您的目标是坚持使用普通的、普通的java,请阅读其他设计模式,例如,策略、访问者、观察者。它们通常可以解决与多个调度相同的问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48213295

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档