[英]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.