在Scala中引用不带类型参数的泛型

在Scala中引用不带类型参数的泛型,scala,generics,Scala,Generics,我正在Scala中创建一个树结构,试图实现以下类型限制: 非根节点是三种类型之一—时间节点、开始节点或结束节点 根节点只有时间节点类型的子节点 时间节点仅具有“开始节点”类型的子节点 开始节点仅具有结束节点类型的子节点 结束节点可以具有“开始节点”或“时间节点”类型的子节点 以下是我的类型定义: trait TreeNode[U] { val children:HashSet[NonRootNode[U]] def addChild(c:NonRootNode[U]) } class No

我正在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 {
    
    }
    
    因为一个明显的类型匹配。
    行被注释后,this.addChild发出尖叫,因为它被未定义的ChildType绑定。

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

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

    最后,我添加了一个标记trait,
    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 }
    
    trait树节点{
    
    现在我有了一个名为addTimeNodes()的方法,它应该能够接受RootNode或EndNode作为参数(因为这两种类型的节点都接受TimeNode类型的子节点).I定义了一个由RootNode和EndNode类实现的trait WithTimeChildren。addTimeNodes方法的签名应该是什么?addTimeNodes(节点:带WithTimeChildren的TreeNode)当我试图将TimeNode传递给node.addChild时,抱怨类型与node.ChildType不匹配,这基本上是因为编译器不知道在这种情况下ChildType可以是什么。@navjotk不确定您到底想要什么-addTimeNode是其中一种TreeNode类型上的方法吗?您可以再显示一些代码吗(或作为新问题提问)?更新了问题。@navjotk-Hmm,您可以通过更改新trait中的类型值以给出边界而不是确切的定义来编译它:
    type ChildType>:TimeNode
    
    case class EndNode(l:Option[String]) extends NonRootNode with ParentOfTimeNode{ type ChildType = NonRootNode with IntervalMarker }
    
    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 }