Scala Type Parameters 2

879 阅读1分钟

  • 类型关系

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] 使用
    }