1

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?

Rogach
  • 26,050
  • 21
  • 93
  • 172

1 Answers1

3

Are you asking how to abstract over the return type of add? If so, you might want to look into functional dependencies. See also CanBuildFrom from the Scala collections, as described here and here.

Community
  • 1
  • 1
Kipton Barros
  • 21,002
  • 4
  • 67
  • 80