1

我正在 Scala 中创建一个树结构,试图实现以下类型限制:

  1. 非根节点是三种类型之一 - 时间节点、开始节点或结束节点
  2. 根节点只有时间节点类型的子节点
  3. 时间节点只有开始节点类型的子节点
  4. 开始节点只有结束节点类型的子节点
  5. 结束节点可能有类型为开始节点或时间节点的子节点

这些是我的类型定义:

trait TreeNode[U] {
val children:HashSet[NonRootNode[U]]
  def addChild(c:NonRootNode[U])
}

class NonRootNode[T <: TreeNode[T]] extends TreeNode[T] {
  var passengers:Set[Passenger] = Set()
  val children:HashSet[T] = new HashSet[T]
  def addChild(c:T) = {
    children.add(c)
  }
}

case class RootNode extends TreeNode[TimeNode] {
    val children:HashSet[TimeNode] = new HashSet[TimeNode]
    def addChild(c:TimeNode) = {
      children.add(c)
    }
}

case class TimeNode(time:Int) extends NonRootNode[StartNode] {

}

case class StartNode(l:Option[String]) extends NonRootNode[EndNode] {

}

case class EndNode(l:Option[String]) extends NonRootNode {

}

首先,这是否正确实现了要求 1-4?其次,有没有办法在定义中实现要求 5?有没有办法实现这个要求,因为这需要一个异构集来存储子引用。

编辑: RootNode 和 EndNode 类型需要如下方法:

trait ParentOfTimeNode extends TreeNode{
  //type ChildType = TimeNode
  def addTimeNodes(startTime:Int, maxTime:Int) = {
      for(i <- startTime to maxTime) {
        this.addChild(new TimeNode(i))
      }
    }
}

如果没有注释该行,则尖叫的行是:

case class EndNode(l:Option[String]) extends NonRootNode with ParentOfTimeNode{ type ChildType = NonRootNode with IntervalMarker }

因为明显的类型匹配。注释了该行后, this.addChild 尖叫,因为它被未定义的 ChildType 绑定。

4

1 回答 1

2

我相信我可以实现您的目标,但使用类型成员而不是类型参数。

此外,这意味着我可以将 addChild 的实现移到特征中,而不是在子类中重新实现它。

最后,我添加了一个标记特征 ,IntervalMarker来标记 EndNode 可以接受为子节点的两种节点类型。

trait TreeNode {
  type ChildType <: NonRootNode
  val children:HashSet[ChildType] = new HashSet[ChildType]
  def addChild(c:ChildType) = {
    children.add(c)
  }
}

abstract class NonRootNode extends TreeNode {
  var passengers:Set[Passenger] = Set()
}

case object RootNode extends TreeNode { type ChildType = TimeNode }

trait IntervalMarker

case class TimeNode(time:Int) extends NonRootNode with IntervalMarker { type ChildType = StartNode }

case class StartNode(l:Option[String]) extends NonRootNode with IntervalMarker { type ChildType = EndNode }

case class EndNode(l:Option[String]) extends NonRootNode { type ChildType = NonRootNode with IntervalMarker }
于 2013-09-04T02:13:39.143 回答