2013-09-03 3 views
0

Я создаю структуру дерева в Scala, пытаясь реализовать следующие ограничения типа:См родовыми без параметра типа в Scala

  1. Некорневых узлы один из трех типов - Time Node, Start Node или End узел
  2. корневого узел имеет только ребенок типа Time Node
  3. Время Nodes только дети типа Start Node
  4. Start Вершина только у детей типа конечного узла
  5. Конечных узлов могут иметь ребенок типа Start Узел или Время Узел

Это мои определения типа:

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 здесь в определении? Есть ли способ реализовать это требование, поскольку для этого потребуется гетерогенный набор для хранения ссылок на детей.

EDIT: Типы 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, который не определен.

ответ

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 } 
+0

Практически там. Теперь у меня есть метод под названием addTimeNodes(), который должен иметь возможность принимать либо RootNode, либо EndNode в качестве параметра (так как это два типа узлов, которые принимают дочерние типы типа TimeNode). Я определил черту WithTimeChildren, которая реализует классы RootNode и EndNode. Какая должна быть подпись метода addTimeNodes? addTimeNodes (node: TreeNode с WithTimeChildren) жалуется на несоответствие типов с node.ChildType, когда я пытаюсь передать TimeNode на node.addChild, что в основном связано с тем, что компилятор не знает, каким может быть ChildType в этом случае. – navjotk

+0

@navjotk Не уверен, что вы хотите здесь точно - это addTimeNode метод на одном из типов TreeNode? Можете ли вы показать еще какой-нибудь код (или задать новый вопрос)? – Shadowlands

+0

Обновлен вопрос. – navjotk

Смежные вопросы