泛型 #

一、泛型类 #

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