应用程序可以以两种模式运行 - "实时"它在哪里查看世界状况的每次更新,或者"采样"它只在每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中可行吗?如果没有,那么实现这种类型安全的惯用方法是什么?
答案 0 :(得分:9)
在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编码的数据类型递归的值。 Scott编码对应于实际模式匹配。无论如何,访问者可以用来实现所有这些编码。感谢nudge,@ user3237465!