I need to model a node in a tree. Node has children, of course, and there is inheritance hierarchy of nodes:
trait Node extends Seq[Node] {
val children:List[Node] = List()
def apply(n:Int) = children(n)
def iterator = children.iterator
def length = children.length
def add(n:Node):Node = { ??? }
}
case class NodeA(n:Int) extends Node
case class NodeB(n:String) extends Node
case class NodeC(c:String) extends NodeB(c)
val na:NodeA = new NodeA(1)
val na1:NodeA = na.add(new NodeB("a"))
na1.children == List(NodeB("a"))
val na2:NodeA = na1.add(new NodeC("b"))
na2.children == List(NodeB("a"), NodeC("b"))
The problem here is that I want to keep Node and its subclasses immutable.
That's then I begin having problems. How do I write method .add on Node properly? Because obviously calling NodeA.add should return NodeA, not Node.
The collateral damage is that even if I put all Node-specific methods implementations (children
, add
, remove
) into each of subclasses (or into companion objects, builders, CanBuildFrom's, etc), then I'll need to define children
as a constructor parameter. Which would clutter Node subclasses definition and usage - I should avoid it if possible.
Is this possible? Or am I doing something wrong and there is another way?