在Haskell中,我可以定义以下数据类型:
data Tree = Empty
| Leaf Int
| Node Tree Tree
然后像这样编写多态函数:
depth :: Tree -> Int
depth Empty = 0
depth (Leaf n) = 1
depth (Node l r) = 1 + max (depth l) (depth r)
在Java中,我可以使用接口模拟代数数据类型:
interface Tree {}
class Empty implements Tree {}
class Leaf implements Tree { int n; }
class Node implements Tree { Tree l; Tree r; }
但是如果我尝试使用类似 Haskell 的多态性,我会得到一个错误:
int depth(Empty node) {
return 0;
}
int depth(Leaf node) {
return 1;
}
int depth(Node node) {
return 1 + Math.max(depth(node.l), depth(node.r)); // ERROR: Cannot resolve method 'depth(Tree)'
}
克服这个问题的正确方法是将方法放在 depth()
每个类中。但是如果我不想把它放在那里怎么办?例如,方法depth()
可能与类没有直接关系Tree
,将其添加到类会破坏业务逻辑。或者,更糟糕的是,Tree
可能是在我无法访问的 3rd 方库中编写的。在这种情况下,实现类似 ADT 的多态性的最简单方法是什么?
以防万一,目前我正在使用以下语法,这显然是不受欢迎的:
int depth(Tree tree) {
if (tree instanceof Empty) depth((Empty)tree)
if (tree instanceof Leaf) depth((Leaf)tree);
if (tree instanceof Node) depth((Node)tree);
else throw new RuntimeException("Don't know how to find depth of " + tree.getClass());
}