1. 泛型类
带有一个或多个类型参数的类是泛型的。
泛型类的定义:
//带有类型参数A的类定义
class Stack[A] {
private var elements: List[A] = Nil
//泛型方法
def push(x: A) { elements = x :: elements }
def peek: A = elements.head
def pop(): A = {
val currentTop = peek
elements = elements.tail
currentTop
}
}
使用上述的泛型类,使用具体的类型代替类型参数 A 。
val stack = new Stack[Int]
stack.push(1)
stack.push(2)
println(stack.pop) // prints 2
println(stack.pop) // prints 1
2. 协变
定义一个类型 List[+A],如果 A 是协变的,意思是:对类型 A 和 B,A 是 B 的子类型,那么 List[A] 是 List[B] 的子类型。
abstract class Animal {
def name: String
}
case class Cat(name: String) extends Animal
case class Dog(name: String) extends Animal
Scala 标准库有一个泛型类 sealed abstract class List[+A],因为其中的类型参数是协变的,那么下面的程序调用时成功的。
object CovarianceTest extends App {
//定义参数类型List[Animal]
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"))
//传入参数类型为List[Cat]
printAnimalNames(cats)
// Whiskers
// Tom
//传入参数类型为List[Dog]
printAnimalNames(dogs)
// Fido
// Rex
}
定义一个类型 Writer[-A],如果 A 是逆变的,意思是:对类型 A 和 B,A 是 B 的子类型,那么 Writer[B] 是 Writer[A] 的子类型。
abstract class Animal {
def name: String
}
case class Cat(name: String) extends Animal
case class Dog(name: String) extends Animal
定义对应上述类进行操作的打印信息类。
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")
//定义参数类型为Printer[Cat]
def printMyCat(printer: Printer[Cat]): Unit = {
printer.print(myCat)
}
val catPrinter: Printer[Cat] = new CatPrinter
val animalPrinter: Printer[Animal] = new AnimalPrinter
printMyCat(catPrinter)
//可以传入参数类型为Printer[Animal]
printMyCat(animalPrinter)
}
3. 上界
上界定义: 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"
}
//参数类型须是Pet类型的子类
class PetContainer[P <: Pet](p: P) {
def pet: P = p
}
//Dog是Pet类型的子类
val dogContainer = new PetContainer[Dog](new Dog)
//Cat是Pet类型的子类
val catContainer = new PetContainer[Cat](new Cat)
//Lion不是Pet类型的子类,编译通不过
// val lionContainer = new PetContainer[Lion](new Lion)
4. 下界
语法 B >: A 表示参数类型或抽象类型 B 须是类型 A 的父类。通常,A 是类的类型参数,B 是方法的类型参数。
上面这段代码,因为作为协变类型的 B,出现在需要逆变类型的函数参数中,导致编译不通过。解决这个问题,就需要用到下界的概念。
trait Node[+B] {
def prepend[U >: B](elem: U): Node[U]
}
case class ListNode[+B](h: B, t: Node[B]) extends Node[B] {
def prepend[U >: B](elem: U): ListNode[U] = ListNode(elem, this)
def head: B = h
def tail: Node[B] = t
}
case class Nil[+B]() extends Node[B] {
def prepend[U >: B](elem: U): ListNode[U] = ListNode(elem, this)
}
测试
trait Bird
case class AfricanSwallow() extends Bird
case class EuropeanSwallow() extends Bird
val africanSwallowList= ListNode[AfricanSwallow](AfricanSwallow(), Nil())
val birdList: Node[Bird] = africanSwallowList
birdList.prepend(new EuropeanSwallow)
本文为原创文章,如果对你有一点点的帮助,别忘了点赞哦!比心!如需转载,请注明出处,谢谢!