Scala 入门笔记 - 泛型相关

mac2022-06-30  22

[T <: A] UpperBound 上界:T的上界是A类型,即T的父类是A类型

abstract class Animal { def name: String}abstract class Pet extends Animal {}class Cat extends Pet { override def name: String = "Cat"}class Dog extends Pet { override def name: String = "Dog"}class Lion extends Animal { override def name: String = "Lion"}class UpperBoundDemo2[P <: Pet](p: P) { def pet: P = p}object UpperBoundDemo2 { def main(args: Array[String]): Unit = { val dogContainer = new UpperBoundDemo2[Dog](new Dog) val catContainer = new UpperBoundDemo2[Cat](new Cat) println(dogContainer.pet.name) // 这行编译会报错,因为UpperBoundDemo2 要求 P 必须是 Pet的子类,而Lion是继承于Animal的 val lionContainer = new UpperBoundDemo2[Lion](new Lion) }}

  

[B >: A] LowerBound 下界:B类是的子类是A

trait Node[+B] { // 因为函数的参数是逆变,返回是协变,所以此处需要用到下界,来传入B的父类U,满足逆变 def prepend[U >: B](elem: U): Node[U] } case class ListNode[+B](h: B, t: Node[B]) extends Node[B] { override def prepend[U >: B](elem: U): Node[U] = ListNode(elem, this) def head: B = h def tail: Node[B] = t } case class Nil[+B]() extends Node[B] { override def prepend[U >: B](elem: U): Node[U] = ListNode(elem, this) } object LowerBoundClass extends App { trait Bird case class AffricanSwallow() extends Bird case class EuropeanSwallow() extends Bird val affricanSwallowList = ListNode[AffricanSwallow](AffricanSwallow(), Nil()) val birdList: Node[Bird] = affricanSwallowList birdList.prepend(new EuropeanSwallow) }

  

[B <% A] ViewBound 表示B类型需要转换成A类型,需要一个隐式转换函数

[B : A] ContextBound 需要一个隐式转换的值

 

  [-A] 逆变, 作为参数类型,如果A是T的子类,那么C[T]是C[A]的子类

  

abstract class Printer[-A] { def print(value: A): Unit } class AnimalPrinter extends Printer[AnimalC] { override def print(value: AnimalC): Unit = { println("This Animal's name is: " + value.name) } } class CatPrinter extends Printer[CatC] { override def print(value: CatC): Unit = { println("This Cat's name is: " + value.name) } } object ContravarianceTest extends App { val myCat: CatC = CatC("Tom") def printMyCat(printer: Printer[CatC]): Unit = { printer.print(myCat) } val catPrinter: Printer[CatC] = new CatPrinter val animalPrinter: Printer[AnimalC] = new AnimalPrinter // Printer[AnimalC] 可以替换 Printer[CatC] 而反过来不可以 printMyCat(catPrinter) printMyCat(animalPrinter) }

  

  [+B] 协变,作为返回类型,如果B是T的子类,那么C[B]是C[T]的子类

如下面例子,cat、dog都是Animal的子类,Scala标准库中有 sealed abstract class List[+A],所以List[cat], list[dog]都可以替换

List[Animal]的位置,因为cat、dog都是Animal的子类

abstract class AnimalC { def name: String } case class CatC(name: String) extends AnimalC case class DogC(name: String) extends AnimalC class CovarianceTest { } object CovarianceTest extends App { def printAnimalName(animals: List[AnimalC]): Unit = { animals.foreach(animal => println(animal.name)) } val cats: List[CatC] = List(CatC("Tom"), CatC("Jack")) val dogs: List[DogC] = List(DogC("Nill"), DogC("Jim")) printAnimalName(cats) printAnimalName(dogs) }

  

 

转载于:https://www.cnblogs.com/sunnystone85/p/11371417.html

最新回复(0)