ADT-like polymorphism in Java (without altering class)
- by ffriend
In Haskell I can define following data type:
data Tree = Empty
| Leaf Int
| Node Tree Tree
and then write polymorphic function like this:
depth :: Tree -> Int
depth Empty = 0
depth (Leaf n) = 1
depth (Node l r) = 1 + max (depth l) (depth r)
In Java I can emulate algebraic data types with interfaces:
interface Tree {}
class Empty implements Tree {}
class Leaf implements Tree { int n; }
class Node implements Tree { Tree l; Tree r; }
But if I try to use Haskell-like polymorphism, I get an error:
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)'
}
Correct way to overcome this is to put method depth() to each class. But what if I don't want to put it there? For example, method depth() may be not directly related to Tree and adding it to class would break business logic. Or, even worse, Tree may be written in 3rd party library that I don't have access to. In this case, what is the simplest way to implement ADT-like polymorpism?
Just in case, for the moment I'm using following syntax, which is obviously ill-favored:
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());
}