0

让我从一个例子开始。

假设我有一个抽象Vehicle类。

public abstract class Vehicle {

    public Vehicle() {}

    public abstract void ride();

}

而类CarBicycle继承自这个抽象类。

public class Car extends Vehicle {

    public Car() {}

    @Override
    public void ride() {
        System.out.println("Riding the car.");
    }

}

public class Bicycle extends Vehicle {

    public Bicycle() {}

    @Override
    public void ride() {
        System.out.println("Riding the bicycle.");
    }

}

当我将该ride()方法应用于Vehicle实际类型只能在运行时确定的类型对象时,JVM 将应用正确版本的ride().

也就是说,在 sort 的柯里化方法调用中v.ride(),多态以预期的方式工作。

但是,如果我有一个只接受一个子类型Vehicle作为参数的方法形式的外部实现呢?那么,如果我有repair(Bicycle b)repair(Car c)方法呢?uncurried 多态方法调用repair(v)将不起作用。

例子:

import java.util.ArrayList;
import java.util.List;

public class Main {

private static void playWithVehicle() {
    List<Vehicle> garage = new ArrayList<Vehicle>();
    garage.add(new Car());
    garage.add(new Car());
    garage.add(new Bicycle());
    garage.forEach((v) -> v.ride()); // Works.
    garage.forEach((v) -> {
        /* This would be nice to have.
        repair(v.castToRuntimeType());
        */

        // This is an ugly solution, but the obvious way I can think of.
        switch (v.getClass().getName()) {
        case "Bicycle":
            repair((Bicycle) v);
            break;
        case "Car":
            repair((Car) v);
            break;

        default:
            break;
        }
    });
}

private static void repair(Bicycle b) {
    System.out.println("Repairing the bicycle.");
}

private static void repair(Car c) {
    System.out.println("Repairing the car.");
}

public static void main(String[] args) {
    playWithVehicle();
}

}

我必须检查班级名称和沮丧。有没有更好的解决方案?


编辑:我的实际目的是我正在遍历一个抽象语法树,我碰巧注意到我想要双重调度。

Ast是一个抽象类,实际的 AST 节点(如AssignMethodCall或)从中ReturnStmt继承。bodyAsts 的多态列表。

代码片段:

List<Ast> body;

body.parallelStream().forEach((ast) -> {
    // This one won't work.
    visit(ast);
    // This one will work.
    if (ast instanceof Assign) {
        visit((Assign) ast);
    } else if (ast instance of MethodCall) {
        visit((MethodCall) ast);
    } else if (ast instance of ReturnStmt) {
        visit((ReturnStmt) ast);
    }
    // etc. for other AST nodes
});

private void visit(Assign ast) {

}

private void visit(MethodCall ast) {

}

private void visit(ReturnStmt ast) {

}

我实现双重调度的唯一可能性是检查类和向下转换或正确实现访问者模式,对吗?

4

1 回答 1

0

:Java 中没有多重分派,它可以instanceof通过访问者模式或访问者模式来模拟。

见这里: Java 方法重载 + 双分派

另请参阅:https ://en.wikipedia.org/wiki/Multiple_dispatch#Examples_of_emulating_multiple_dispatch

在旁注中,这在 C# 中通过dynamic调用是可能的:如何使用扩展构建双重调度

这在编译为 JVM 字节码的许多语言中也是可能的,例如提到了 Groovy。

于 2015-11-01T15:26:18.967 回答