泛型 #
一、泛型类 #
1.1 基本语法 #
scala
class Box[T](value: T):
def get: T = value
def map[U](f: T => U): Box[U] = Box(f(value))
val intBox = Box(42)
val stringBox = Box("Hello")
println(intBox.get)
println(stringBox.get)
1.2 泛型数据结构 #
scala
class Pair[A, B](val first: A, val 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 pair = Pair(1, "hello")
println(pair.first)
println(pair.swap)
1.3 泛型容器 #
scala
class Container[T]:
private var item: Option[T] = None
def put(value: T): Unit = item = Some(value)
def get: Option[T] = item
def isEmpty: Boolean = item.isEmpty
def map[U](f: T => U): Container[U] =
val newContainer = Container[U]()
item.foreach(v => newContainer.put(f(v)))
newContainer
val container = Container[Int]()
container.put(42)
println(container.get)
二、泛型方法 #
2.1 定义泛型方法 #
scala
def identity[T](x: T): T = x
def middle[T](list: List[T]): Option[T] =
if list.isEmpty then None
else Some(list(list.length / 2))
def swap[A, B](pair: (A, B)): (B, A) = (pair._2, pair._1)
identity(42)
identity("hello")
middle(List(1, 2, 3, 4, 5))
swap((1, "hello"))
2.2 泛型工厂方法 #
scala
class ListBuilder[T]:
private var items = List.empty[T]
def add(item: T): ListBuilder[T] =
items = item :: items
this
def build: List[T] = items.reverse
object ListBuilder:
def apply[T](): ListBuilder[T] = ListBuilder[T]()
def from[T](items: T*): ListBuilder[T] =
val builder = ListBuilder[T]()
items.foreach(builder.add)
builder
val list = ListBuilder.from(1, 2, 3, 4, 5).build
三、类型约束 #
3.1 上界(Upper Bound) #
scala
class Animal:
def name: String = "Animal"
class Dog extends Animal:
override def name: String = "Dog"
class Kennel[T <: Animal]:
def describe(animal: T): String = s"This is a ${animal.name}"
val kennel = Kennel[Dog]()
println(kennel.describe(Dog()))
3.2 下界(Lower Bound) #
scala
class Animal
class Dog extends Animal
class Cat extends Animal
class Container[T]:
def add[U >: T](item: U): List[U] = List(item)
val dogContainer = Container[Dog]()
val animals: List[Animal] = dogContainer.add(Animal())
3.3 视图界定(View Bound) #
Scala 3 中已弃用,使用上下文界定代替:
scala
def max[T](a: T, b: T)(using ord: Ordering[T]): T =
if ord.compare(a, b) > 0 then a else b
max(10, 20)
max("hello", "world")
3.4 上下文界定 #
scala
def sum[T](list: List[T])(using num: Numeric[T]): T =
list.sum
sum(List(1, 2, 3, 4, 5))
sum(List(1.0, 2.0, 3.0))
四、型变 #
4.1 不变(Invariant) #
scala
class Container[T](val value: T)
val a: Container[Animal] = Container[Dog](Dog())
4.2 协变(Covariant) #
使用 + 标记:
scala
class Box[+T](val value: T)
class Animal
class Dog extends Animal
val dogBox: Box[Dog] = Box(Dog())
val animalBox: Box[Animal] = dogBox
4.3 逆变(Contravariant) #
使用 - 标记:
scala
trait Printer[-T]:
def print(value: T): String
class Animal
class Dog extends Animal
val animalPrinter: Printer[Animal] = new Printer[Animal]:
def print(value: Animal): String = s"Animal: ${value.getClass.getSimpleName}"
val dogPrinter: Printer[Dog] = animalPrinter
4.4 型变规则 #
| 位置 | 协变 | 逆变 | 不变 |
|---|---|---|---|
| 返回类型 | ✓ | ✗ | ✓ |
| 参数类型 | ✗ | ✓ | ✓ |
| 可变字段 | ✗ | ✗ | ✓ |
五、类型约束实战 #
5.1 类型类 #
scala
trait Show[T]:
def show(value: T): String
object Show:
given Show[Int] with
def show(value: Int): String = value.toString
given Show[String] with
def show(value: String): String = value
given Show[Boolean] with
def show(value: Boolean): String = value.toString
def printShow[T](value: T)(using show: Show[T]): Unit =
println(show.show(value))
printShow(42)
printShow("hello")
printShow(true)
5.2 多态比较 #
scala
def max[T](a: T, b: T)(using ord: Ordering[T]): T =
if ord.compare(a, b) > 0 then a else b
def sort[T](list: List[T])(using ord: Ordering[T]): List[T] =
list.sorted
max(10, 20)
max("hello", "world")
sort(List(3, 1, 4, 1, 5))
5.3 数值操作 #
scala
def sum[T](list: List[T])(using num: Numeric[T]): T =
list.sum
def average[T](list: List[T])(using num: Numeric[T]): Double =
num.toDouble(sum(list)) / list.length
sum(List(1, 2, 3, 4, 5))
average(List(1.0, 2.0, 3.0, 4.0, 5.0))
六、高级泛型 #
6.1 抽象类型成员 #
scala
trait Container:
type T
def value: T
def describe: String = s"Container with ${value.getClass.getSimpleName}"
class IntContainer(val value: Int) extends Container:
type T = Int
class StringContainer(val value: String) extends Container:
type T = String
val intContainer: Container { type T = Int } = IntContainer(42)
val stringContainer: Container { type T = String } = StringContainer("hello")
6.2 路径依赖类型 #
scala
class Outer:
class Inner(val value: Int)
def createInner(v: Int): Inner = Inner(v)
val outer1 = Outer()
val outer2 = Outer()
val inner1: outer1.Inner = outer1.createInner(1)
val inner2: outer2.Inner = outer2.createInner(2)
6.3 F-Bounded Polymorphism #
scala
trait Comparable[T <: Comparable[T]]:
def compareTo(other: T): Int
class Person(val name: String, val age: Int) extends Comparable[Person]:
def compareTo(other: Person): Int = this.age.compareTo(other.age)
七、泛型最佳实践 #
7.1 使用有意义的类型参数名 #
scala
class Pair[Key, Value](val key: Key, val value: Value)
class Result[Success, Error](val result: Either[Error, Success])
7.2 优先使用不可变泛型类 #
scala
class Box[+T](val value: T)
7.3 使用上下文界定 #
scala
def process[T: Show](value: T): String =
summon[Show[T]].show(value)
八、总结 #
型变速查 #
| 类型 | 语法 | 说明 |
|---|---|---|
| 协变 | +T | 子类型关系保持 |
| 逆变 | -T | 子类型关系反转 |
| 不变 | T | 无子类型关系 |
类型约束 #
| 约束 | 语法 | 说明 |
|---|---|---|
| 上界 | T <: Upper | T 必须是 Upper 的子类型 |
| 下界 | T >: Lower | T 必须是 Lower 的超类型 |
| 上下文界定 | T: Context | 存在 Context[T] 的隐式值 |
下一步,让我们学习 隐式转换!
最后更新:2026-03-27