Skip to content

Scala 模式匹配

模式匹配(Pattern matching)是 Scala 最强大且最常用的特性之一。它允许你将一个值与一系列模式进行比较,并执行相应的代码块,从而简化复杂的条件逻辑,特别是在处理结构化数据时。

模式匹配表达式以一个值开头,后跟 match 关键字和一个包含 case 子句的块。每个 case 定义一个模式和一个表达式(=> expression),如果值匹配该模式,则执行该表达式。第一个匹配成功的模式的表达式会被求值。

这是一个简单的整数匹配示例:

@main def PatternMatchDemo(): Unit = {
def describe(x: Int): String = x match {
case 1 => "one"
case 2 => "two"
case n if n > 2 && n < 10 => s"a small number ($n)" // 模式守卫
case _ => "something else" // 通配符模式
}
println(describe(1))
println(describe(5))
println(describe(100))
}

输出:

one
a small number (5)
something else

示例中的关键元素:

  • case 1 => ...: 匹配字面值 1。
  • case n if n > 2 ...: 匹配任何整数,将其绑定到 n,并应用一个守卫条件(if)。
  • case _ => ...: 通配符 _ 匹配之前所有 case 都未捕获的任何内容。它对于确保模式覆盖所有可能性(穷举性)至关重要。

你也可以基于值的类型进行匹配,这在使用 Any 时特别有用:

@main def TypeMatchDemo(): Unit = {
def matchType(x: Any): String = x match {
case i: Int => s"It's an Integer: $i"
case s: String => s"It's a String: $s"
case d: Double => s"It's a Double: $d"
case _: List[_] => "It's a List of something"
case _ => "It's something else"
}
println(matchType(42))
println(matchType("Hello Scala"))
println(matchType(3.14))
println(matchType(List(1, 2, 3)))
println(matchType(true))
}

输出:

It's an Integer: 42
It's a String: Hello Scala
It's a Double: 3.14
It's a List of something
It's something else

模式 s: String 检查 x 是否是 String 类型,并(如果匹配)将其绑定到一个类型为 String 的变量 s。

Case Class 专门设计用于与模式匹配无缝协作。它们自动提供伴生对象(companion objects),包含 apply 和 unapply 方法,使得构建和解构(deconstruction)变得容易。

// 定义一个 case class
case class Person(name: String, age: Int)
@main def CaseClassMatchDemo(): Unit = {
val alice = Person("Alice", 30)
val bob = Person("Bob", 25)
val charlie = Person("Charlie", 30)
for (person <- List(alice, bob, charlie)) {
person match {
case Person("Alice", 30) => println(s"Hi Alice!")
case Person("Bob", age) => println(s"Hi Bob! You are $age years old.")
case Person(name, 30) => println(s"Hi $name! You are 30.")
case Person(name, age) => println(s"Who are you, $name of age $age?")
}
}
}

输出:

Hi Alice!
Hi Bob! You are 25 years old.
Hi Charlie! You are 30.

case class 的优势:

  1. 默认不可变字段(构造器参数成为 val 字段)。
  2. 自动实现基于构造器参数的 equals, hashCode, 和 toString 方法。
  3. 自动生成 apply 方法(例如,Person("Alice", 30) 而非 new Person(...))。
  4. 自动生成 unapply 方法,使得在模式匹配中轻松进行解构(例如,case Person(name, age) => ...)。

模式匹配在 Scala 中广泛应用于各种任务,例如:处理 Actor 系统(如 Akka)中的消息、处理可选值(Option)、处理计算结果(Try 或 Either)、解构复杂数据结构(如 JSON 或 XML 树),以及实现状态机。

探索集合的匹配(例如 List(1, 2, _*))、Option 的匹配(Some(v) vs None),以及如何使用提取器(extractor,unapply 方法)实现自定义模式匹配逻辑。查阅官方 Scala 文档以了解更多高级模式。