Scala中的模式匹配-基础使用

37 阅读2分钟

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. 注意事项

  1. 完整性检查:使用-Xfatal-warnings编译选项可以警告非完整匹配
  2. 性能:模式匹配通常编译为高效的表跳转或if-else链
  3. 变量名:小写字母开头的模式会绑定变量,大写字母开头的匹配常量

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的核心特性之一,它使代码更简洁、更安全、更具表达力,是函数式编程的重要工具。