应用程序可以在两种模式下运行 - “实时”模式(它查看世界状态的每次更新)或“采样”模式(它仅每 T 毫秒查看一次世界状态)。
如果我正在编写 Haskell(或任何带有 ADT 的语言),我会将其建模为
data Mode = RealTime | Sampled Int
可以以类型安全的方式如下使用
case mode of
RealTime -> -- do realtime stuff
Sampled interval -> -- do sample stuff with 'interval'
我说它是“类型安全的”,因为如果您在实时模式下运行,您将无法尝试访问 interval
字段(它仅在您运行时提供)如果您在采样模式下操作,则需要它)。
如何以类型安全的方式在 Java 中对同一事物建模?也就是我要
- 定义一个区分这两种模式的类(或枚举),以及
- 在实时模式下禁止访问
interval
字段,以及 - 让编译器检查所有这些。
这在 Java 中可行吗?如果不是,实现这种类型安全的惯用方法是什么?
最佳答案
在像 Java 这样只以类型安全的方式提供开放类(可以随时继承)的语言中模拟封闭代数数据类型的传统方法是 Visitor pattern :
abstract class Mode {
public abstract <T> T accept(ModeVisitor<T> visitor);
}
final class RealTime extends Mode {
public RealTime() {}
public <T> T accept(ModeVisitor<T> visitor) {
return visitor.visit(this);
}
}
final class Sampled extends Mode {
private final int interval;
public Sampled(int interval) {
this.interval = interval;
}
public int getInterval() {
return this.interval;
}
public <T> T accept(ModeVisitor<T> visitor) {
return visitor.visit(this);
}
}
// The recursion principle itself
abstract class ModeVisitor<T> {
public abstract T visit(RealTime mode);
public abstract T visit(Sampled mode);
}
// Concrete uses of the recursion principle
final class ModeShow extends ModeVisitor<String> {
private ModeShow() {}
public static String show(Mode mode) {
return mode.accept(new ModeShow());
}
public String visit(RealTime mode) {
return "RealTime";
}
public String visit(Sampled mode) {
return "Sampled " + mode.getInterval();
}
}
正如@user3237465 所指出的,数据类型的几种编码是可能的,当数据类型不是递归时,它们碰巧重合:Church 编码是一种折叠:它允许您累积一个值通过对 Church 编码数据类型的递归。 Scott 编码对应于实际的模式匹配。无论如何,访问者都可以用来实现所有这些编码。感谢@user3237465 的鼓励!
关于java - 在 Java 中模拟 ADT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31428870/