Scala for Backend Engineering & Functional Programming · 课时

穷尽式匹配

由编译器检查完整性

第 4 / 4 课13 个步骤

穷尽式匹配 是 CoddyKit 上的免费 Scala for Backend Engineering & Functional Programming 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Scala for Backend Engineering & Functional Programming 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。

什么是穷举匹配

当 match 处理了被匹配类型的每个可能值时,它就是穷举的。

对于 sealed Trait,编译器知道所有变体,并可以检查 match 是否覆盖了它们。

完整匹配

当您处理 sealed Trait 的每个变体时,编译器就不会报出警告。

sealed trait Color
case object Red extends Color
case object Green extends Color
case object Blue extends Color
object Main {
  def name(c: Color): String = c match {
    case Red   => "red"
    case Green => "green"
    case Blue  => "blue"
  }
  def main(args: Array[String]): Unit = {
    println(name(Blue))
  }
}

编译器为您保驾护航

如果遗漏了某个变体,编译器会在编译时发出非穷举匹配警告。

这是一道安全防线:您可以在运行程序前发现遗漏。

之后添加变体

添加新变体时,穷举匹配的真正价值就体现出来了。代码库中每个非穷举匹配都会显示警告,提醒您处理新的分支。

这让重构变得安全且可预期。

为什么避免使用通配符

添加 case _ => 会隐藏穷举性警告。之后添加变体时,这可能掩盖错误。

对于 sealed ADT,建议明确列出每个变体,以便编译器持续保护您的代码。

sealed trait Status
case object Active extends Status
case object Inactive extends Status
object Main {
  def label(s: Status): String = s match {
    case Active   => "on"
    case Inactive => "off"
  }
  def main(args: Array[String]): Unit = {
    println(label(Active))
  }
}

带数据的穷举性

穷举性同样适用于携带数据的变体。您需要绑定字段,同时仍然必须覆盖每个变体。

sealed trait Shape
case class Circle(r: Double) extends Shape
case class Square(s: Double) extends Shape
object Main {
  def area(sh: Shape): Double = sh match {
    case Circle(r) => 3.14159 * r * r
    case Square(s) => s * s
  }
  def main(args: Array[String]): Unit = {
    println(area(Circle(2)))
    println(area(Square(3)))
  }
}

结合守卫条件

请注意:守卫条件可能使匹配变得非穷举,因为编译器无法证明这些条件覆盖了所有值。

请为同一个变体提供一个不带守卫条件的最终分支,以保持穷举性。

sealed trait Temp
case class Celsius(v: Int) extends Temp
object Main {
  def feel(t: Temp): String = t match {
    case Celsius(v) if v >= 30 => "hot"
    case Celsius(v)            => "not hot"
  }
  def main(args: Array[String]): Unit = {
    println(feel(Celsius(35)))
    println(feel(Celsius(10)))
  }
}

使用 Option 的穷举性

标准库中的 Option 是一个 sealed ADT,包含 Some 和 None。匹配这两者即可实现穷举。

object Main {
  def show(o: Option[Int]): String = o match {
    case Some(v) => s"value $v"
    case None    => "nothing"
  }
  def main(args: Array[String]): Unit = {
    println(show(Some(7)))
    println(show(None))
  }
}

嵌套结构的穷举性

穷举性也能帮助处理嵌套 ADT。编译器会分析您拆解的每一层结构。

sealed trait Tree
case object Leaf extends Tree
case class Node(v: Int, l: Tree, r: Tree) extends Tree
object Main {
  def depth(t: Tree): Int = t match {
    case Leaf          => 0
    case Node(_, l, r) => 1 + math.max(depth(l), depth(r))
  }
  def main(args: Array[String]): Unit = {
    println(depth(Node(1, Leaf, Node(2, Leaf, Leaf))))
  }
}

为什么这很重要

由编译器检查穷举性,可以带来以下好处:

  • 确信每个分支都已处理
  • ADT 扩展时自动提醒
  • 更少的运行时 MatchErrors
  • 更安全的大规模重构

整合运用

一个覆盖完整的 sealed ADT。如果在这里添加新变体,编译器就会发出警告。

sealed trait Command
case object Start extends Command
case object Stop extends Command
case class SetSpeed(v: Int) extends Command
object Main {
  def run(c: Command): String = c match {
    case Start       => "starting"
    case Stop        => "stopping"
    case SetSpeed(v) => s"speed $v"
  }
  def main(args: Array[String]): Unit = {
    List(Start, SetSpeed(5), Stop).foreach(c => println(run(c)))
  }
}

快速检查

检验您对穷举匹配的理解。

回顾

您已经学习了穷举匹配:

  • 覆盖每个变体时,匹配就是穷举的
  • 对于 sealed Trait,编译器会检查这一点,并对遗漏发出警告
  • 添加变体会暴露所有不完整的匹配
  • 在 sealed ADT 上避免使用 case _,以保留这种保护
  • 守卫条件可能破坏穷举性;请添加一个不带守卫条件的后备分支
免费开始

用 AI 导师学习 Scala — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
39
课程
143

常见问题解答

「穷尽式匹配」课时是免费的吗?

是的 — 「穷尽式匹配」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Scala for Backend Engineering & Functional Programming 课程的其余内容,请升级到 CoddyKit PRO。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。

「穷尽式匹配」这节课中我会学到什么?

由编译器检查完整性 你通过在浏览器中直接运行的动手代码来练习 Scala for Backend Engineering & Functional Programming,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Scala for Backend Engineering & Functional Programming 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Scala for Backend Engineering & Functional Programming 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「穷尽式匹配」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Scala for Backend Engineering & Functional Programming 课中编写并运行代码吗?

能。每节 Scala for Backend Engineering & Functional Programming 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 样例类
  2. 密封特质
  3. 代数数据类型
  4. 穷尽式匹配
← 返回 Scala for Backend Engineering & Functional Programming