我在Scala中创建树结构,试图实现以下类型限制:
这些是我的类型定义:
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绑定。
答案 0 :(得分: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 }