Scala 入门笔记 - 泛型相关

[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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值