文章目录

Scala 模式匹配:match 表达式与 case 类

发布于 2026-04-06 11:27:19 · 浏览 14 次 · 评论 0 条

Scala 模式匹配:match 表达式与 case 类

模式匹配是 Scala 语言最强大的特性之一,它类似于 Java 中的 switch 语句,但功能更为丰富。它不仅可以匹配值,还可以匹配类型、结构和表达式。通过 match 表达式与 case 类的结合,可以极大地简化代码逻辑。


一、 基础 match 表达式

match 表达式由 match 关键字和多个 case 块组成。每个 case 块定义了一个模式,如果匹配成功,则执行该块对应的逻辑。

  1. 打开 REPL 终端或 IDE。
  2. 定义 一个变量。
  3. 输入 以下代码,使用 match 关键字进行匹配:
val number = 3

val description = number match {
  case 1 => "一"
  case 2 => "二"
  case 3 => "三"
  case _ => "其他"
}
  1. 观察 输出结果。
    • number 的值为 3,程序依次对比 case 1case 2,均不匹配。
    • 当对比到 case 3 时匹配成功,返回 字符串 "三"
    • case _ 是通配符,类似于 Java 中的 default,用于匹配所有未被前面条件捕获的情况。

二、 模式匹配中的守卫

如果需要在匹配时增加额外的条件判断,可以使用守卫。守卫通过 if 关键字在 case 语句后添加布尔表达式。

  1. 编写 包含守卫的匹配表达式:
val score = 85

val grade = score match {
  case s if s >= 90 => "优秀"
  case s if s >= 60 => "及格"
  case _ => "不及格"
}
  1. 执行 代码。
    • 变量 score 的值为 85
    • 第一个 case 尝试匹配,判断 85 >= 90false,跳过。
    • 第二个 case 尝试匹配,判断 85 >= 60true赋值 s85返回 "及格"

三、 Case 类的定义与使用

case 类是一种特殊的类,它们默认是不可变的,并且自动实现了 applyhashCodeequalstoString 等方法,非常适合用于模式匹配。

  1. 定义 一个 case 类结构:
case class Person(name: String, age: Int)
  1. 创建 实例。
    • 不需要使用 new 关键字,直接 调用 类名即可:
val alice = Person("Alice", 25)

四、 匹配 Case 类结构

模式匹配的真正威力在于解构复杂对象。可以直接在 case 语句中提取 case 类内部的字段。

  1. 编写 针对 case 类的匹配逻辑:
val user = Person("Bob", 15)

val greeting = user match {
  case Person("Alice", _) => "你好,Alice"
  case Person(name, age) if age < 18 => s"你好,未成年用户 $name"
  case Person(name, _) => s"你好,$name"
}
  1. 分析 匹配过程:
    • userPerson("Bob", 15)
    • 第一个 case 要求名字必须是 "Alice",匹配失败。
    • 第二个 case 提取名字为 name,年龄为 age,并检查 age < 18。此时 age15,条件成立,返回 "你好,未成年用户 Bob"

五、 匹配类型与嵌套结构

除了匹配具体的值和对象结构,还可以匹配变量的运行时类型,以及嵌套的对象结构。

  1. 定义 一个通用的匹配方法,处理不同类型的数据:
def process(input: Any): String = input match {
  case i: Int => s"收到整数: $i"
  case s: String => s"收到字符串: $s"
  case Person(name, age) => s"收到 Person 对象: $name"
  case _ => "未知类型"
}
```

2.  **测试** 不同的输入:

```scala
process(10)          // 输出: 收到整数: 10
process("hello")    // 输出: 收到字符串: hello
process(Person("Tom", 30)) // 输出: 收到 Person 对象: Tom
```

3.  **处理** 嵌套结构。
    *   假设有一个 `case` 类包含另一个 `case` 类:

```scala
case class Student(school: String, person: Person)

val complexData = Student("一中", Person("Mike", 16))

val result = complexData match {
  case Student(school, Person(name, _)) => s"$name 就读于 $school"
}
```

4.  **执行** 上述代码,程序将直接 **提取** 出嵌套在 `Student` 内部的 `Person` 对象的 `name` 字段,**输出** `"Mike 就读于 一中"`。

---

### 六、 密封类

为了保证模式匹配的完备性(即覆盖所有可能的情况),通常将父类标记为 `sealed`(密封的)。编译器会检查是否所有子类都已匹配,若未覆盖全,编译器会发出警告。

1.  **定义** 一个密封特质(Trait):

```scala
sealed trait Message
case class Text(content: String) extends Message
case class Image(url: String) extends Message
case class Video(duration: Int) extends Message
```

2.  **编写** 处理消息的函数:

```scala
def handleMessage(msg: Message): Unit = msg match {
  case Text(content) => println(s"文本: $content")
  case Image(url) => println(s"图片链接: $url")
  // 如果这里注释掉 Video 的分支,编译器会报出警告
  case Video(duration) => println(s"视频时长: $duration")
}
  1. 确认 编译状态。
    • 如果 遗漏Video 分支的匹配,编译器会提示 match may not be exhaustive,这有助于避免运行时错误。

七、 实战案例:简单的通知系统

结合上述知识点,构建一个简单的通知系统,处理不同类型的消息。

  1. 定义 基础数据结构:
sealed trait Notification
case class Email(sender: String, title: String) extends Notification
case class SMS(caller: String, msg: String) extends Notification
case class PushAlert(level: Int, content: String) extends Notification
  1. 编写 处理逻辑函数:
def processNotification(note: Notification): String = note match {
  case Email(sender, title) if sender == "boss" =>
    s"紧急邮件来自 $sender: $title"

  case Email(sender, title) =>
    s"普通邮件: $title (来自 $sender)"

  case SMS("10086", msg) =>
    s"系统通知短信: $msg"
    
  case SMS(caller, msg) =>
    s"短信来自 $caller: $msg"
    
  case PushAlert(level, content) if level >= 3 =>
    s"高优先级提醒: $content"

  case PushAlert(_, content) =>
    s"普通提醒: $content"
}
  1. 调用 函数并验证结果:
val email = Email("boss", "会议通知")
val sms = SMS("10086", "余额不足")
val alert = PushAlert(5, "系统异常")

println(processNotification(email))  // 输出: 紧急邮件来自 boss: 会议通知
println(processNotification(sms))    // 输出: 系统通知短信: 余额不足
println(processNotification(alert)) // 输出: 高优先级提醒: 系统异常

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文