2

我正在尝试在节点与其父节点之间的图中强制执行类型关系。我有以下内容无法在 child.parents ::= this 上编译。欢迎任何评论

  trait TGraphNode {
    type NodeType <: TGraphNode
    var id = -1
    var parents = List[NodeType]()
    var children = List[TGraphNode]()

    def addChild(child: NodeType) {
      children ::= child
      child.parents ::= this
    }

    override def toString = "node-"+id+"->"+children
  }

抱歉 - 下次会添加编译错误。我正在尝试实现以下目标:假设我有 2 个类型为 F 和 C 的节点 - 我想通过构造强制 C 只能将 F 作为父级,但是,反过来我不在乎。F可以有C,D..作为孩子。所以我想捕捉到 ParentType 可以在实现特征的类中被覆盖。

class F extends TGraphNode ...
class B extends TGraphNode {
  type ParentType = F
}

谢谢

4

2 回答 2

2

错误信息是

error: Type mismatch 
 found   : TGraphNode.this.type (with underlying type TGraphNode)
 required: child.NodeType
             child.parents ::= this

(请不要在您的问题中省略)

您的代码声明节点可以选择其父节点所需的类型,类型为 variable NodeType。这种类型必须符合 TGraphNode,但它可能比这更受限制。

鉴于此,child添加的类型可能addChild需要比this其父类型更受限制的类型。编译器拒绝它是正确的。

这就是错误消息的内容:您放入this了孩子的父母列表。this有类型TGraphNode。但是parents列表是NodeType子列表的 ( child.NodeType) 并不能保证比类型匹配。

如果您不解释您要达到的目标,我无法进一步评论。


编辑后:

您必须声明您将在 addChild 中仅接受一个接受此作为父母的孩子。这可能有点棘手,这是一种可能的方法:

def addChild[N](child: TGraphNode{type NodeType = N})
               (implicit thisAsParentOfChild : this.type <:< N) {
  children ::= child
  child.parents ::= thisAsParentOfChild(this)
}

完成后,您现在可以这样做

class F extends TGraphNode {type NodeType = TGraphNode }
class C extends TGraphNode {type NodeType = F }
class X extends TGraphNode {type NodeType = TGraphNode } 

val f = new F
val c = new C
val x = new X

f.addChild(c) // ok 
x.addChild(f) // ok

x.addChild(c) // error: Cannot prove that x.type <:< F

如果您不知道 <:< 类型的隐式参数是做什么的,请查看 <:<、<%< 和 =:= 在 Scala 2.8 中的含义,以及它们在哪里记录?


在重新考虑和阅读 bluenote 建议时,写作addParentaddChild您的上下文要简单得多(我相信这是颠倒孩子和父母的正确方法):

def addParent(parent: NodeType) {
  parents ::= parent
  parent.children ::= this
} 
于 2012-11-08T17:31:17.447 回答
1

我的猜测是,您只是混淆了类型NodeTypeTGraphNode. 如果我理解正确,孩子可能是TGraphNode. 至少这是addChild函数签名所表明的,并且可能是更可能的用例。所以,孩子必须是类型NodeType,但父母可以有更一般的TGraphNode类型,即:

trait TGraphNode {
  type NodeType <: TGraphNode
  var id = -1
  var children = List[NodeType]()
  var parents = List[TGraphNode]()

  def addChild(child: NodeType) {
    children ::= child
    child.parents ::= this
  }

  override def toString = "node-"+id+"->"+children
}

编辑:

好吧,你真的想要反过来。由于上面提到的版本编译,你可以颠倒孩子和父母的定义来得到你想要的。

于 2012-11-08T17:32:06.057 回答