簡體   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