Scala的密封抽象与抽象类

Posted

技术标签:

【中文标题】Scala的密封抽象与抽象类【英文标题】:Scala's sealed abstract vs abstract class 【发布时间】:2011-03-03 05:52:20 【问题描述】:

sealed abstractabstract Scala 类有什么区别?

【问题讨论】:

【参考方案1】:

不同之处在于密封类的所有子类(无论是否抽象)都必须与密封类在同一个文件中。

【讨论】:

不太明显的事情(至少不适合我:-))是密封类的“孙子”也可以在其他文件中:给定密封类A; B 扩展 A; C 扩展 B。B 必须与 A 在同一个文件中,但 C 可以留在同一个文件中或另一个文件中。 @SandorMurakozi 如果您想实现这一点,您也必须将 B 声明为密封类。密封只处理直接继承。【参考方案2】:

作为answered,所有直接继承密封类(抽象或非抽象)的子类必须在同一个文件中。这样做的一个实际结果是,如果模式匹配不完整,编译器会发出警告。例如:

sealed abstract class Tree
case class Node(left: Tree, right: Tree) extends Tree
case class Leaf[T](value: T) extends Tree
case object Empty extends Tree

def dps(t: Tree): Unit = t match 
  case Node(left, right) => dps(left); dps(right)
  case Leaf(x) => println("Leaf "+x)
  // case Empty => println("Empty") // Compiler warns here

如果Treesealed,则编译器会发出警告,除非最后一行未注释。

【讨论】:

如果没有sealed关键字,为什么编译器不能推断模式匹配不完整? @sasha.sochka 假设我编译它并把它放在一个 jar 文件中,没有 sealed 关键字。那时所有内容都已编译,包括match 语句。现在,另一个用户抓住了这个罐子并扩展了Tree。没有什么能阻止他这样做,但是,在这一点上,match 声明不再完整。由于他没有编译它,只是从你的 jar 中使用它,编译器无法警告 。而且由于您在创建 jar 时不知道它,它不可能警告您。 @DanielCSobral,您写道“但是,在那个点,匹配语句不再完整”。在制作 jar 文件之前,当您编译发布的原始代码(但没有 sealed 关键字)时,匹配语句不是不完整的吗?看起来很容易推断,因为即使没有新的孩子(编译器还不知道他们),Empty 也没有分支。我说的是对创建罐子的人的警告,而不是对使用它的人的警告。 @sasha.sochka 好吧,我想它可能会警告Empty 丢失,但关键是,即使您添加Empty,它仍然可能不完整,也可能不完整,具体取决于单独编译时会发生什么。 是的,那我同意你的看法。

以上是关于Scala的密封抽象与抽象类的主要内容,如果未能解决你的问题,请参考以下文章

12. 抽象与密封

C# 中基类,虚类,抽象类,密封类,接口的区别

jqc#零基础学习之路抽象类和密封

kotlin抽象类密封类接口

在密封类中为抽象 val 赋值

抽象类上的 Json.reads(不支持密封特征:没有已知的子类)