簡體   English   中英

Scala類型界限行為(方法與類)

[英]Scala type bounds behaviour (method vs class)

對於Scala專家來說,這可能是一件容易的事。 我正在閱讀類型綁定約束,並想知道是否遺漏了一些東西,因為我看到了一些意想不到的行為。 假設我們在這樣的層次結構中有三種類型A,B,C,我們正在針對它們進行類型界限的實驗:

class A {
}

class B extends A {
}

class C extends B {
}

class MyList1 { // T super B
  def add[T >: B](a: T): Unit = {}
}

class MyList2 { // T extends B
  def add[T <: B](a: T): Unit = {}
}

class MyList3[T >: B] { // T super B
  def add(a: T): Unit = {}
}

class MyList4[T <: B] { // T extends B
  def add(a: T): Unit = {}
}

object BoundsClass {

  def main(args: Array[String]) {
    val l1 = new MyList1
    l1.add(new A) 
    l1.add(new B)
    l1.add(new C) // why is this allowed??

    val l2 = new MyList2
    // l2.add(new A) // not allowed (OK)
    l2.add(new B)
    l2.add(new C)

    val l3a = new MyList3[A]
    val l3b = new MyList3[B]
    // val l3c = new MyList3[C] // not allowed (OK)

    // val l4a = new MyList4[A] // not allowed (OK)
    val l4b = new MyList4[B]
    val l4c = new MyList4[C]
  }

}

除一種情況外,其他所有集合的行為均符合預期,請參見l1.add(new C);。 不會導致編譯錯誤。 為什么允許這樣做?

謝謝!

我並沒有聲稱自己是斯卡拉大律師,但我會為此而a之以鼻。

您已經按照A >: B >: C定義了類型層次結構,因此您可以執行以下操作

val aa: A = new A
val ab: A = new B
val ac: A = new C

val bb: B = new B
val bc: B = new C

val cc: C = new C

就像您可以說val a: Any = new Whatever

因此,當您嘗試向l1添加new C時,它會被視為B實例,因為這是它自身最接近該方法的類型范圍的可用版本。

當以這種方式使用時,下界沒有用。 您不能將value參數強制設置為下限,因為根據Liskov替換原則 ,您必須能夠在需要類實例的任何地方使用子類實例。 因此,您的代碼可以編譯,因為new C可以視為B的實例。

通常,由於這個原因,在方法的值參數上設置下限是沒有用的。 在您綁定類的類型參數的第二種情況下,下界無疑更有用。 所有類型參數都是按編譯類型解析的,因此,您可以期望編譯器在第二種情況下產生編譯器錯誤。 您可以在此處找到下限用法的更具體示例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM