第4章:模式匹配
一、导读
1.1 本章学习目标
第4章讲解 Scala 强大的模式匹配:match 表达式、提取器、模式类型。
本章核心学习目标:
- 掌握 match 表达式:替代 switch
- 理解提取器(Extractor):自定义模式
- 掌握各种模式类型:常量、变量、类型、守卫
1.2 为什么本章如此重要
模式匹配是 Scala 最强大的特性之一。它让复杂条件逻辑变得清晰优雅。
1.3 核心问题引导
模式匹配比 if/else 有什么优势?
提取器如何工作?
什么是模式守卫?
二、核心概念详解
4.1 基本模式匹配
scala
// 常量匹配
def describe(x: Any): String = x match {
case 0 => "zero"
case 1 => "one"
case "hello" => "greeting"
case true => "truth"
case _ => "something else"
}
// 类型匹配
def typeOf(x: Any): String = x match {
case s: String => s"String: $s"
case i: Int => s"Int: $i"
case d: Double => s"Double: $d"
case list: List[_] => s"List of ${list.size} elements"
case _ => "unknown"
}
// 带守卫的模式
def classify(n: Int): String = n match {
case x if x < 0 => "negative"
case 0 => "zero"
case x if x > 0 && x <= 10 => "small positive"
case x if x > 10 => "large positive"
}4.2 集合模式
scala
// 列表模式
val list = List(1, 2, 3, 4, 5)
list match {
case Nil => "empty"
case head :: tail => s"head: $head, tail: $tail"
case List(1, 2, _*) => "starts with 1, 2"
case List(_, _, x, _*) => s"third element: $x"
}
// 元组模式
val point = (3, 4)
point match {
case (0, 0) => "origin"
case (x, 0) => s"on x-axis at $x"
case (0, y) => s"on y-axis at $y"
case (x, y) => s"at ($x, $y)"
}
// case 类模式
sealed trait Shape
case class Circle(radius: Double) extends Shape
case class Rectangle(width: Double, height: Double) extends Shape
def area(shape: Shape): Double = shape match {
case Circle(r) => math.Pi * r * r
case Rectangle(w, h) => w * h
}4.3 提取器
scala
// 自定义提取器
object Email {
def unapply(str: String): Option[(String, String)] = {
val parts = str.split("@")
if (parts.length == 2) Some((parts(0), parts(1)))
else None
}
}
// 使用
"alice@example.com" match {
case Email(user, domain) => println(s"User: $user, Domain: $domain")
case _ => println("Not an email")
}
// 变量提取器
object Twice {
def apply(s: String): String = s + s
def unapply(s: String): Option[String] = {
val length = s.length / 2
if (length * 2 == s.length && s.substring(0, length) == s.substring(length))
Some(s.substring(0, length))
else None
}
}
"abcabc" match {
case Twice(x) => println(s"Repeated: $x") // Repeated: abc
case _ => println("Not repeated")
}三、实战案例
3.1 案例一:JSON 解析器
scala
sealed trait JsonValue
case class JsonString(value: String) extends JsonValue
case class JsonNumber(value: Double) extends JsonValue
case class JsonBool(value: Boolean) extends JsonValue
case class JsonNull() extends JsonValue
case class JsonArray(values: List[JsonValue]) extends JsonValue
case class JsonObject(fields: Map[String, JsonValue]) extends JsonValue
def prettyPrint(json: JsonValue, indent: Int = 0): String = {
val pad = " " * indent
json match {
case JsonString(s) => s""""$s""""
case JsonNumber(n) => n.toString
case JsonBool(b) => b.toString
case JsonNull() => "null"
case JsonArray(values) =>
val items = values.map(v => prettyPrint(v, indent + 1))
s"[\n${items.map(i => pad + " " + i).mkString(",\n")}\n$pad]"
case JsonObject(fields) =>
val items = fields.map { case (k, v) =>
s""""$k": ${prettyPrint(v, indent + 1)}"""
}
s"{\n${items.map(i => pad + " " + i).mkString(",\n")}\n$pad}"
}
}
val json = JsonObject(Map(
"name" -> JsonString("Alice"),
"age" -> JsonNumber(30),
"scores" -> JsonArray(List(JsonNumber(95), JsonNumber(87)))
))
println(prettyPrint(json))四、本章小结
match 表达式是强大的条件分支工具
提取器通过 unapply 自定义匹配逻辑
sealed trait + case 类配合模式匹配实现代数数据类型
五、思考与练习
模式匹配的穷举检查如何工作?
如何实现一个正则表达式提取器?