Scala的模式匹配(Pattern Matching)是一种强大且优雅的特性,它比Java/C++的switch语句更强大,可以匹配各种模式,包括值、类型、集合结构等。
1. 基本语法
// 基本格式
value match {
case pattern1 => result1
case pattern2 => result2
case _ => defaultResult // 默认情况
}
// 示例
def describe(x: Any): String = x match {
case 1 => "数字一"
case "hello" => "打招呼"
case true => "布尔真"
case _ => "其他"
}
2. 匹配类型
// 匹配类型并提取值
def processValue(x: Any): String = x match {
case s: String => s"字符串: $s"
case i: Int => s"整数: $i"
case d: Double => s"双精度: $d"
case list: List[_] => s"列表,长度: ${list.length}"
case _ => "未知类型"
}
// 使用
processValue("hello") // "字符串: hello"
processValue(List(1,2,3)) // "列表,长度: 3"
3. 解构匹配
// 匹配元组
val point = (1, 2)
point match {
case (0, 0) => "原点"
case (x, 0) => s"X轴上: $x"
case (0, y) => s"Y轴上: $y"
case (x, y) => s"点($x, $y)"
}
// 匹配列表
def listMatch(list: List[Int]): String = list match {
case Nil => "空列表"
case head :: Nil => s"只有一个元素: $head"
case head :: tail => s"头部: $head, 尾部: $tail"
}
// 匹配case class
case class Person(name: String, age: Int)
def personMatch(p: Person): String = p match {
case Person("Alice", age) => s"Alice, 年龄: $age"
case Person(name, 18) => s"$name 刚好18岁"
case Person(name, age) => s"姓名: $name, 年龄: $age"
}
4. 带守卫的条件匹配
def checkNumber(x: Int): String = x match {
case n if n < 0 => "负数"
case n if n == 0 => "零"
case n if n > 0 && n < 10 => "个位数正数"
case _ => "其他正数"
}
// 结合解构使用
(x, y) match {
case (a, b) if a == b => "对角线"
case (a, b) if a < b => "上方区域"
case _ => "其他"
}
5. 密封类与模式匹配
// 密封类常用于模式匹配
sealed trait Animal
case class Dog(name: String) extends Animal
case class Cat(color: String) extends Animal
case class Bird(canFly: Boolean) extends Animal
def animalSound(animal: Animal): String = animal match {
case Dog(name) => s"$name 说: 汪汪!"
case Cat(_) => "喵喵!"
case Bird(true) => "飞翔的鸟叫!"
case Bird(false) => "不会飞的鸟叫!"
// 不需要默认分支,因为sealed trait的所有子类已知
}
6. 使用@绑定变量
val list = List(1, 2, 3, 4)
list match {
// @符号允许同时使用整体和部分
case fullList @ List(1, 2, _*) =>
s"以1,2开头,完整列表: $fullList"
case head :: tail @ List(2, 3, 4) =>
s"头部: $head, 特定尾部: $tail"
}
7. 偏函数中的模式匹配
// 偏函数只处理部分输入
val partial: PartialFunction[Int, String] = {
case 1 => "一"
case 2 => "二"
case 3 => "三"
}
// 检查是否定义
partial.isDefinedAt(1) // true
partial.isDefinedAt(4) // false
8. 实际应用示例
// 解析命令
case class Command(cmd: String, args: List[String])
def execute(cmd: Command): String = cmd match {
case Command("exit", _) => "退出程序"
case Command("help", Nil) => "显示帮助"
case Command("search", query :: Nil) => s"搜索: $query"
case Command("copy", src :: dest :: Nil) => s"从$src复制到$dest"
case Command(cmd, args) => s"未知命令: $cmd,参数: $args"
}
// 处理JSON-like结构
sealed trait Json
case class JString(value: String) extends Json
case class JNumber(value: Double) extends Json
case class JObject(fields: Map[String, Json]) extends Json
def jsonToString(json: Json): String = json match {
case JString(s) => s""""$s""""
case JNumber(n) => n.toString
case JObject(fields) =>
fields.map { case (k, v) => s""""$k": ${jsonToString(v)}""" }
.mkString("{", ", ", "}")
}
9. 注意事项
- 完整性检查:使用
-Xfatal-warnings编译选项可以警告非完整匹配 - 性能:模式匹配通常编译为高效的表跳转或if-else链
- 变量名:小写字母开头的模式会绑定变量,大写字母开头的匹配常量
10. 最佳实践
// 使用Option进行安全匹配
val maybeName: Option[String] = Some("Alice")
maybeName match {
case Some(name) => println(s"Hello, $name")
case None => println("No name provided")
}
// 或使用更简洁的方式
maybeName.foreach(name => println(s"Hello, $name"))
// 避免模式匹配嵌套过深
// 不好
value match {
case Some(x) => x match {
case Some(y) => // ...
}
}
// 好
value match {
case Some(Some(y)) => // ...
}
模式匹配是Scala的核心特性之一,它使代码更简洁、更安全、更具表达力,是函数式编程的重要工具。