Scala中的匹配模式(二)

35 阅读2分钟

基础语法

val x: Int = 3

val result = x match {
  case 1 => "one"
  case 2 => "two"
  case _ => "other"  // 默认情况
}

println(result)  // 输出: other

一、基本匹配类型

1. 值匹配

def describe(num: Int): String = num match {
  case 1 => "One"
  case 2 => "Two"
  case 3 => "Three"
  case _ => "Many"
}

2. 类型匹配(类型守卫)

def matchType(value: Any): String = value match {
  case x: Int    => s"Int: $x"
  case x: String => s"String: $x"
  case x: Double => s"Double: $x"
  case _         => "Unknown type"
}

println(matchType(42))      // Int: 42
println(matchType("hello")) // String: hello

二、高级匹配模式

1. 元组匹配

val point = (2, 3)

point match {
  case (0, 0) => "原点"
  case (x, 0) => s"X轴上的点: ($x, 0)"
  case (0, y) => s"Y轴上的点: (0, $y)"
  case (x, y) => s"普通点: ($x, $y)"
}

2. 列表匹配

val list = List(1, 2, 3)

list match {
  case Nil => "空列表"
  case head :: Nil => s"只有一个元素: $head"
  case first :: second :: rest => s"第一个: $first, 第二个: $second, 其余: $rest"
  case _ => "其他"
}

3. 数组匹配

def matchArray(arr: Array[Int]): String = arr match {
  case Array(1, 2, 3) => "包含 1, 2, 3"
  case Array(_, 5)    => "第二个元素是5的二元数组"
  case Array(x, y, z) => s"三元数组: $x, $y, $z"
  case _              => "其他数组"
}

三、守卫条件(Guard)

val num = 15

num match {
  case x if x < 10 => "小于10"
  case x if x > 10 && x < 20 => "10到20之间"
  case x if x % 2 == 0 => "偶数"
  case _ => "其他"
}

四、样例类(Case Class)匹配

// 定义样例类
sealed trait Animal
case class Dog(name: String, age: Int) extends Animal
case class Cat(name: String, color: String) extends Animal
case class Bird(species: String) extends Animal

def describeAnimal(animal: Animal): String = animal match {
  case Dog(name, age) => s"一只 $age 岁的狗,名叫 $name"
  case Cat(name, color) => s"一只 $color 色的猫,名叫 $name"
  case Bird(species) => s"一只 $species 鸟"
  case _ => "未知动物"
}

五、Option 类型匹配

val maybeValue: Option[Int] = Some(42)

maybeValue match {
  case Some(value) => s"有值: $value"
  case None => "无值"
}

// 更简洁的写法
val result = maybeValue.getOrElse("默认值")

六、正则表达式匹配

val emailPattern = """^(\w+)@([\w\.]+)$""".r

"user@example.com" match {
  case emailPattern(user, domain) => 
    s"用户: $user, 域名: $domain"
  case _ => "无效邮箱"
}

七、偏函数(Partial Function)

val isEven: PartialFunction[Int, String] = {
  case x if x % 2 == 0 => s"$x 是偶数"
}

val isOdd: PartialFunction[Int, String] = {
  case x if x % 2 != 0 => s"$x 是奇数"
}

val checkNumber = isEven orElse isOdd

println(checkNumber(4))  // 4 是偶数
println(checkNumber(7))  // 7 是奇数

八、提取器(Extractor)

object Even {
  def unapply(x: Int): Option[Int] = 
    if (x % 2 == 0) Some(x) else None
}

object Odd {
  def unapply(x: Int): Option[Int] = 
    if (x % 2 != 0) Some(x) else None
}

5 match {
  case Even(n) => s"$n 是偶数"
  case Odd(n)  => s"$n 是奇数"
}

九、@ 操作符(绑定变量)

val list = List(List(1, 2), List(3, 4))

list match {
  case firstList @ List(1, _*) :: rest => 
    s"第一个列表: $firstList, 其余: $rest"
  case _ => "其他"
}

// 匹配并命名整个模式
list match {
  case all @ List(List(1, 2), _*) =>
    s"整个结构: $all"
}

十、密封类(Sealed Class)与穷尽性检查

sealed trait Color
case object Red extends Color
case object Green extends Color
case object Blue extends Color

def colorCode(color: Color): String = color match {
  case Red => "#FF0000"
  case Green => "#00FF00"
  case Blue => "#0000FF"
  // 不需要 default case,编译器会检查是否覆盖所有情况
}

使用建议

  1. 尽量使用 match 代替嵌套的 if-else
  2. 利用编译器穷尽性检查(使用密封类时)
  3. 模式匹配比反射性能更好
  4. 样例类 + 模式匹配是 Scala 的强大组合

性能考虑

  • Scala 的模式匹配在编译时会优化为 switch 语句或查找表
  • 对于简单的值匹配,性能接近 switch
  • 复杂的模式匹配可能有额外开销