- 类型关系
Scala 支持在泛型类上使用型变注释,用来表示复杂类型、组合类型的子类型关系间的相关性
- 协变
+T,变化方向相同,通常用在生产
> 假设 `A extends T`, 对于 `Clazz[+T]`,则 `Clazz[A]` 也可看做 `Clazz[T]`
// 官网示例
abstract class Animal {
def name: String
}
case class Cat(name: String) extends Animal
case class Dog(name: String) extends Animal
由于 Scala 标准库中不可变 `List` 的定义为 `List[+A]`,因此 `List[Cat]` 是 `List[Animal]` 的子类型, `List[Dog]` 也是 `List[Animal]` 的子类型,所以可直接将他们当作 `List[Animal]` 使用。
// 官网示例
object CovarianceTest extends App {
def printAnimalNames(animals: List[Animal]): Unit = {
animals.foreach { animal =>
println(animal.name)
}
}
val cats: List[Cat] = List(Cat("Whiskers"), Cat("Tom"))
val dogs: List[Dog] = List(Dog("Fido"), Dog("Rex"))
printAnimalNames(cats)
// Whiskers
// Tom
printAnimalNames(dogs)
// Fido
// Rex
}
- 逆变
-T,变化方向相反,通常用在消费
> 假设 `A extends T`, 对于 `Clazz[-T]`,则 `Clazz[T]` 也可看做 `Clazz[A]`
// 官网示例
abstract class Printer[-A] {
def print(value: A): Unit
}
class AnimalPrinter extends Printer[Animal] {
def print(animal: Animal): Unit =
println("The animal's name is: " + animal.name)
}
class CatPrinter extends Printer[Cat] {
def print(cat: Cat): Unit =
println("The cat's name is: " + cat.name)
}
object ContravarianceTest extends App {
val myCat: Cat = Cat("Boots")
def printMyCat(printer: Printer[Cat]): Unit = {
printer.print(myCat)
}
val catPrinter: Printer[Cat] = new CatPrinter
val animalPrinter: Printer[Animal] = new AnimalPrinter
printMyCat(catPrinter)
printMyCat(animalPrinter) // 将 Printer[Animal] 当作 Printer[Cat] 使用
}