Scala 逆變協變
阿新 • • 發佈:2022-01-29
協變:在期望接收一個基類集合的地方使用子類例項集合的能力
逆變:在期望接收一個子類集合的地方使用基類例項集合的能力
在預設情況下,scala不允許使用協變和逆變,稱之為不變
舉個例子:我們定義兩個class,一個是Pet,一個是Dog,讓Dog繼承自Pet。
然後我們呼叫一個方法,在接Array[Pet]的地方傳入Array[Dog]
在標紅處,會提示type mismatch,說明預設情況不支援協變。
但是,我們可以通過特殊的語法來支援協變。
這裡T <: Pet 表示T派生自Pet,Pet為T的上界,傳入陣列至少得是Array[Pet],或者其子類集合。
反之,也可以支援逆變,在接收子類集合的地方傳入基類集合
這裡Dog是T的下界。
前面介紹的,都是在方法引數做的型變。如果我們需要自定義資料格式的話,我們也可以使用”+T”或者“-T”來支援協變和逆變。
舉個例子,前面我們定義的pets和dogs。
如果直接賦值的話,會提示type mismatch。
我們自己定義一個Array,“+T”表示支援協變。
petArray期望接收一個MyArray[Pet],但是接收了MyArray[Dog]。
反之,“-T”支援逆變
完整程式碼
object test extends App { def workWithPet(pets:Array[Pet]): Unit ={ } var dogs = Array[Dog](new Dog("bill"), new Dog("bob")) // workWithPet(dogs) def workWithPet2[T <: Pet](pets:Array[T]): Unit ={ } workWithPet2(dogs) var pets = Array[Pet](new Pet("bill"), new Pet("bob")) def workWithPet3[T >: Dog](dogs:Array[T]): Unit ={ } workWithPet3(pets) // pets = dogs // dogs = pets var dogArray = new MyArray[Dog]() var petArray = new MyArray[Pet]() petArray = dogArray var dogArray2 = new MyArray2[Dog]() var petArray2 = new MyArray2[Pet]() dogArray2 = petArray2 } class MyArray[+T]{ } class MyArray2[-T]{ } class Pet(name: String) { override def toString: String = name def behavior(): Unit = { println("This is a Pet.") } } class Dog(name: String) extends Pet(name: String) { override def toString: String = name override def behavior(): Unit = { println("This is a Dog.") } }