1. 基本泛型语法
1.1 泛型类
// 定义泛型类
class Box[T](value: T) {
def getValue: T = value
def setValue(newValue: T): Box[T] = new Box(newValue)
}
// 使用
val intBox = new Box[Int](42)
val stringBox = new Box[String]("Hello")
println(intBox.getValue) // 42
println(stringBox.getValue) // Hello
1.2 泛型方法
// 泛型方法
def printElement[T](element: T): Unit = {
println(s"元素: $element")
}
def swap[T](a: T, b: T): (T, T) = (b, a)
// 使用
printElement(100) // 元素: 100
printElement("Scala") // 元素: Scala
println(swap(1, 2)) // (2, 1)
println(swap("A", "B")) // (B, A)
2. 类型参数约束
2.1 上界约束(<:)
// 定义类层次结构
abstract class Animal {
def name: String
}
class Dog(val name: String) extends Animal
class Cat(val name: String) extends Animal
class Car(val model: String) // 不是Animal子类
// 上界约束:T必须是Animal或其子类
class AnimalShelter[T <: Animal](animal: T) {
def showAnimal: String = s"收容所动物: ${animal.name}"
}
// 使用
val dogShelter = new AnimalShelter(new Dog("Buddy"))
val catShelter = new AnimalShelter(new Cat("Whiskers"))
// val carShelter = new AnimalShelter(new Car("Tesla")) // 编译错误
2.2 下界约束(>:)
// 下界约束:T必须是Animal或其父类
def addToGroup[T >: Dog](animal: T, group: List[T]): List[T] = animal :: group
val dogs: List[Dog] = List(new Dog("Buddy"), new Dog("Max"))
val animals: List[Animal] = List(new Dog("Buddy"), new Cat("Whiskers"))
addToGroup(new Dog("NewDog"), dogs) // 可以
addToGroup(new Dog("NewDog"), animals) // 可以
2.3 视图界定(<%)- Scala 2.x特性(Scala 3中已移除)
// Scala 2.x中的视图界定
def printValue[T <% Comparable[T]](value: T): Unit = {
println(value)
}
2.4 上下文界定(:)
// 定义类型类
trait Show[T] {
def show(t: T): String
}
// 定义隐式实例
implicit val intShow: Show[Int] = new Show[Int] {
def show(t: Int): String = s"Int: $t"
}
implicit val stringShow: Show[String] = new Show[String] {
def show(t: String): String = s"String: '$t'"
}
// 上下文界定:要求存在隐式的Show[T]实例
def printValue[T: Show](value: T): Unit = {
val showInstance = implicitly[Show[T]]
println(showInstance.show(value))
}
// 使用
printValue(42) // Int: 42
printValue("Hello") // String: 'Hello'
3. 协变和逆变
3.1 协变(+)
// 协变:如果B是A的子类,那么Container[B]是Container[A]的子类
class Container[+T](value: T) {
def get: T = value
// def set(newValue: T): Unit = {} // 协变类型不能出现在方法参数位置
}
class Animal
class Dog extends Animal
val dogContainer: Container[Dog] = new Container(new Dog)
val animalContainer: Container[Animal] = dogContainer // 协变允许向上转型
3.2 逆变(-)
// 逆变:如果B是A的子类,那么Container[B]是Container[A]的父类
trait Printer[-T] {
def print(value: T): Unit
}
class AnimalPrinter extends Printer[Animal] {
def print(animal: Animal): Unit = println(s"Animal: $animal")
}
class DogPrinter extends Printer[Dog] {
def print(dog: Dog): Unit = println(s"Dog: $dog")
}
// 逆变允许向下转型
val dogPrinter: Printer[Dog] = new AnimalPrinter
dogPrinter.print(new Dog) // 可以,AnimalPrinter可以处理Dog
4. 类型通配符
class Animal
class Dog extends Animal
class Cat extends Animal
// 使用通配符
def processAnimals(animals: List[_ <: Animal]): Unit = {
animals.foreach(animal => println(animal))
}
def addAnimal(animals: List[_ >: Dog]): List[Any] = {
new Dog("NewDog") :: animals
}
val dogs: List[Dog] = List(new Dog, new Dog)
val animals: List[Animal] = List(new Dog, new Cat)
processAnimals(dogs) // 可以
processAnimals(animals) // 可以
addAnimal(dogs) // 可以
addAnimal(animals) // 可以
5. 泛型实战示例
5.1 泛型栈实现
class Stack[T] {
private var elements: List[T] = Nil
def push(element: T): Unit = {
elements = element :: elements
}
def pop(): Option[T] = elements match {
case Nil => None
case head :: tail =>
elements = tail
Some(head)
}
def peek: Option[T] = elements.headOption
def isEmpty: Boolean = elements.isEmpty
def size: Int = elements.length
}
// 使用
val intStack = new Stack[Int]
intStack.push(1)
intStack.push(2)
println(intStack.pop()) // Some(2)
val stringStack = new Stack[String]
stringStack.push("Hello")
stringStack.push("World")
5.2 泛型Pair类
case class Pair[A, B](first: A, second: B) {
def swap: Pair[B, A] = Pair(second, first)
def mapFirst[C](f: A => C): Pair[C, B] = Pair(f(first), second)
def mapSecond[C](f: B => C): Pair[A, C] = Pair(first, f(second))
}
// 使用
val pair1 = Pair(42, "Answer")
val pair2 = pair1.swap // Pair("Answer", 42)
val pair3 = pair1.mapFirst(_ * 2) // Pair(84, "Answer")
5.3 泛型排序函数
// 使用Ordering上下文界定
def bubbleSort[T : Ordering](arr: Array[T]): Array[T] = {
val ord = implicitly[Ordering[T]]
val sorted = arr.clone()
for (i <- 0 until sorted.length) {
for (j <- 0 until sorted.length - i - 1) {
if (ord.gt(sorted(j), sorted(j + 1))) {
val temp = sorted(j)
sorted(j) = sorted(j + 1)
sorted(j + 1) = temp
}
}
}
sorted
}
// 使用
val intArray = Array(5, 3, 8, 1, 2)
println(bubbleSort(intArray).mkString(", ")) // 1, 2, 3, 5, 8
val stringArray = Array("banana", "apple", "cherry")
println(bubbleSort(stringArray).mkString(", ")) // apple, banana, cherry
6. 高级泛型特性
6.1 类型别名
type StringMap[V] = Map[String, V]
type IntList = List[Int]
type OptionList[T] = List[Option[T]]
// 使用
val scores: StringMap[Int] = Map("Alice" -> 95, "Bob" -> 87)
6.2 抽象类型成员
trait Container {
type T
def value: T
def setValue(newValue: T): Unit
}
class IntContainer extends Container {
type T = Int
private var _value: Int = 0
def value: Int = _value
def setValue(newValue: Int): Unit = _value = newValue
}
6.3 路径依赖类型
class Outer {
class Inner
def createInner: Inner = new Inner
}
val outer1 = new Outer
val outer2 = new Outer
val inner1: outer1.Inner = outer1.createInner
val inner2: outer2.Inner = outer2.createInner
// val inner3: outer1.Inner = outer2.createInner // 编译错误,类型不匹配
7. 最佳实践
-
命名约定:通常使用单个大写字母作为类型参数名
T:类型(Type)A,B:任意类型E:元素(Element)K:键(Key)V:值(Value)
-
限制泛型使用:只在真正需要的地方使用泛型
-
优先使用上下文界定:而不是视图界定(Scala 2.x)或隐式参数
-
考虑协变/逆变:设计API时考虑类型变体的需求
-
文档化约束:为复杂的泛型约束添加注释说明
8. Scala 3中的新特性
Scala 3引入了更强大的泛型特性:
// 交集类型
type Worker = Employee & Programmer
// 并集类型
type Id = Int | String
// 匹配类型
type ElemType[X] = X match {
case List[t] => t
case Array[t] => t
case _ => X
}