在Scala中引用没有类型参数的泛型

时间:2013-09-03 22:43:12

标签: scala generics

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

  1. 非根节点是三种类型之一 - 时间节点,起始节点或结束节点
  2. 根节点仅具有“时间节点”类型的子节点
  3. 时间节点仅包含Start Node
  4. 类型的子节点
  5. 起始节点仅包含End Node
  6. 类型的子节点
  7. 结束节点可能具有“开始节点”或“时间节点”类型的子节点
  8. 这些是我的类型定义:

    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绑定。

1 个答案:

答案 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 }