0Pricing
Scala for Backend Engineering & Functional Programming · 课时

密封特质

封闭层次结构

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

什么是 Trait

trait 类似于接口:它声明一种公共类型,其他类可以扩展它。

Trait 可以将相关类型归到同一个范畴下,使它们能够互换使用。

基本 Trait

使用 trait 声明 Trait,然后让类或对象通过 extends 扩展它。

trait Shape
case class Circle(r: Double) extends Shape
case class Square(side: Double) extends Shape
object Main {
  def main(args: Array[String]): Unit = {
    val s: Shape = Circle(2.0)
    println(s)
  }
}

sealed 是什么意思

sealed Trait 只能由在同一个文件中声明的类型扩展。

这样层次结构就被封闭了:编译器知道所有可能的子类型。

sealed trait Color
case object Red extends Color
case object Green extends Color
case object Blue extends Color
object Main {
  def main(args: Array[String]): Unit = {
    val c: Color = Green
    println(c)
  }
}

将 Case 对象作为变体

当某个变体不包含数据时,请使用 case object,而不是 case class。它始终只有一个实例。

这非常适合表示类似枚举的值。

sealed trait Direction
case object North extends Direction
case object South extends Direction
object Main {
  def main(args: Array[String]): Unit = {
    val d: Direction = North
    println(d)
  }
}

混合使用对象和类

一个 sealed Trait 可以同时包含 case object 变体(无数据)和 case class 变体(带数据)。

sealed trait Event
case object Started extends Event
case class Failed(reason: String) extends Event
object Main {
  def main(args: Array[String]): Unit = {
    val e: Event = Failed("timeout")
    println(e)
  }
}

匹配 Sealed Trait

您可以针对 Trait 进行匹配,并处理每个变体。由于层次结构是 sealed 的,编译器可以验证您是否覆盖了所有变体。

sealed trait Color
case object Red extends Color
case object Green extends Color
case object Blue extends Color
object Main {
  def hex(c: Color): String = c match {
    case Red   => "#FF0000"
    case Green => "#00FF00"
    case Blue  => "#0000FF"
  }
  def main(args: Array[String]): Unit = {
    println(hex(Green))
  }
}

编译器警告

如果您在对 sealed Trait 进行匹配时忘记了某个变体,编译器会警告您缺少相应分支。

之后添加新变体时,这可以帮助发现错误。我们将在穷举匹配课程中完整讲解这一点。

Trait 可以声明成员

Trait 可以声明所有子类型共享或必须实现的方法或字段。

sealed trait Animal {
  def sound: String
}
case object Dog extends Animal { def sound = "Woof" }
case object Cat extends Animal { def sound = "Meow" }
object Main {
  def main(args: Array[String]): Unit = {
    println(Dog.sound)
    println(Cat.sound)
  }
}

为什么要使用 Sealed

将 Trait 设为 sealed 可以获得以下好处:

  • 已知且封闭的子类型集合
  • 对 match 进行穷举性检查
  • 添加变体时可以更安全地重构

Sealed Trait 加上 case class,就是 Scala 构建代数数据类型的方式。

使用层次结构

函数可以接受 Trait 类型,并通过模式匹配处理任意变体。

sealed trait Payment
case class Cash(amount: Int) extends Payment
case class Card(number: String) extends Payment
object Main {
  def summary(p: Payment): String = p match {
    case Cash(a) => s"cash $a"
    case Card(n) => s"card ending ${n.takeRight(4)}"
  }
  def main(args: Array[String]): Unit = {
    println(summary(Cash(50)))
    println(summary(Card("123456789012")))
  }
}

整合运用

一个包含混合变体的 sealed Trait,通过匹配每个分支的函数来共享处理逻辑。

sealed trait Result
case object Pending extends Result
case class Success(value: Int) extends Result
case class Error(msg: String) extends Result
object Main {
  def show(r: Result): String = r match {
    case Pending    => "waiting"
    case Success(v) => s"ok: $v"
    case Error(m)   => s"fail: $m"
  }
  def main(args: Array[String]): Unit = {
    List(Pending, Success(7), Error("boom")).foreach(r => println(show(r)))
  }
}

快速检查

检验您对 sealed Trait 的理解。

回顾

您已经学习了 sealed Trait:

  • trait 定义共享的超类型
  • sealed 将子类型限制在同一个文件中
  • 无数据的变体使用 case object,带数据的变体使用 case class
  • Sealed 支持对 match 进行穷举性检查

常见问题解答

「密封特质」课时是免费的吗?

是的 — 「密封特质」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 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 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 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