繁体   English   中英

为什么我不能在扩展通用特征的类中调用带有参数“ this”的方法?

[英]Why can't I call a method with parameter `this` in a class extending a generic trait?

我正在写一个特征来描述层次结构(如图形)中的节点状对象。 我的工作代码如下:

trait Hierarchical[T <: Hierarchical[_]] {
  // The parents will be a list of some arbitrary Hierarchical
  val parents: List[Hierarchical[_]] = Nil
  var children: List[Hierarchical[T]] = List()

  def addChild(child: Hierarchical[T]): Unit = {
    children ++= List(child)
  }
}

abstract class NonRootNode(override val parents: List[Hierarchical[_]])
  extends Hierarchical[NonRootNode] {
}

abstract class RootNode extends Hierarchical[NonRootNode] {
  final override val parents = Nil
}

我有一些反映这种行为的测试:

import org.scalatest.FlatSpec

class DummyRoot extends RootNode
class DummyNonRoot(override val parents: List[DummyRoot]) 
  extends NonRootNode(parents)

class TestUtil extends FlatSpec {

  "A RootNode" should "not have parents" in {
    val dummyRoot = new DummyRoot
    assert(dummyRoot.parents.isEmpty)
  }

  "A NonRootNode" should "have parents when constructed with them" in {
    val dummyRoot = new DummyRoot
    assert(dummyRoot.parents.isEmpty)
    val dummyNonRoot = new DummyNonRoot(List(dummyRoot))
    dummyRoot.addChild(dummyNonRoot)
    assert(dummyNonRoot.parents.contains(dummyRoot))
    assert(dummyRoot.children.contains(dummyNonRoot))
  }    
}

但是,我发现第二个测试中的API有点笨拙。 因为我已经指定了孩子的父母,所以我不需要显式地将孩子添加到根节点。 我想从公共API中删除它,所以我的想法是修改NonRootNode的构造函数行为,以便为每个父级调用此函数。 具体来说,我想写:

abstract class NonRootNode(override val parents: List[Hierarchical[_]])
  extends Hierarchical[NonRootNode] {

  //for each parent, add `this` to its children
  parents.map{p=>p.addChild(this)}
}

但是,当我添加此行时,出现以下错误:

Error:(19, 29) type mismatch;
 found   : NonRootNode
 required: Hierarchical[_$3]
  parents.map{p=>p.addChild(this)}

我不确定为什么会出现此编译器错误。 我对Hierarchical[_]理解是任何Hierarchical ,但我可能会误解。 无论如何,我认为我已经接近我想要的行为。 我究竟做错了什么?

Hierarchical[_]并不表示“任何分层”。 这意味着“某种固定类型的层次结构,这是未知的”。

例如

def foo: Hierarchical[_] = new Hierarchical[Int] 

有效:它声明一个函数,该函数将返回Hierarchical某些实现,调用者不知道其确切类型。 这可以。

另一方面:

def bar(h: Hierarchical[String]) = doStuff(h)
bar(foo)

工作:功能bar要确切类型的参数Hierarchical[String] ,什么传递给它不能保证有这种类型,它的类型参数是未知的。

在你的情况, .addChild是一个方法, Hierarchical[T]其中的价值T是您不知道的),并希望同类型的参数。 但是,您要传递给它的是Hierarchical[NonRootNode] 这是非法的,因为无法保证NonRootNode与(未知) T

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM