Как правильно моделировать узел в неоднородном неизменном дереве? - PullRequest
1 голос
/ 23 января 2012

Мне нужно смоделировать узел в дереве. Конечно, у узла есть дочерние элементы, и есть иерархия наследования узлов:

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"))

Проблема в том, что я хочу, чтобы Node и его подклассы оставались неизменными.

Вот тогда у меня начнутся проблемы. Как правильно написать метод .add на Node? Поскольку очевидно, что вызов NodeA.add должен возвращать NodeA, а не Node.
Дополнительный ущерб заключается в том, что даже если я добавлю все реализации методов, специфичные для Node (children, add, remove), в каждый из подклассов (или в объекты-компаньоны, компоновщики, CanBuildFrom и т. Д.), Мне потребуется определить children в качестве параметра конструктора. Что мешало бы определению и использованию подклассов Node - я должен избегать этого, если это возможно.

Возможно ли это? Или я что-то не так делаю и есть другой способ?

1 Ответ

3 голосов
/ 23 января 2012

Вы спрашиваете, как абстрагироваться от типа возвращаемого значения add? Если это так, вы можете изучить функциональные зависимости . См. Также CanBuildFrom из коллекций Scala, как описано здесь и здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...