Scala中最终类和密封类之间有什么区别?

51 scala access-modifiers

Scala中有两种类型的修饰符:finalsealed

它们之间有什么区别?什么时候应该使用另一个?

dca*_*tro 91

一个final班不能延长,期间.

一个sealed特质只能在同一中扩展源文件,因为它的声明.这对于创建ADT(代数数据类型)很有用.ADT 由其派生类型的总和定义.

例如:

  • An Option[A]Some[A]+ 定义None.
  • A List[A]::+ 定义Nil.

sealed trait Option[+A]

final case class Some[+A] extends Option[A]
object None extends Option[Nothing]
Run Code Online (Sandbox Code Playgroud)

因为Option[A]它是密封的,所以它不能被其他开发者扩展 - 这样做会改变它的含义.

Some[A] 是最终的,因为它不能延长,期间.


作为额外的奖励,如果一个特点是密封的,编译器可以,因为它警告你,如果你的模式匹配是不够详尽知道Option限制SomeNone.

opt match {
    case Some(a) => "hello"
}
Run Code Online (Sandbox Code Playgroud)

警告:匹配可能并非详尽无遗.它将在以下输入上失败:None

  • 从技术上讲,"密封"模板可以在同一个*编译单元*中扩展,而不是相同的文件.Scala编译器的编译单元等于文件的事实是一个实现细节.可能有其他编译器使用例如数据库来存储源工件而不是文件系统. (12认同)
  • @JörgWMittag 感谢您的附录,我不知道这种区别。 (2认同)

小智 8

sealed类(或特征)仍然可以在同一个源文件中继承(其中final类根本不能继承).

sealed当您想限制基类的子类数时使用(请参阅"代数数据类型").

作为这种限制的一个非常实际的好处,编译器现在可以警告你关于非执行模式匹配:

sealed trait Duo
case class One(i:Int) extends Duo
case class Two(i:Int, j:Int) extends Duo

def test(d:Duo) {
  match {
    case One(x) => println(x) // warning since you are not matching Two
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 从技术上讲,"密封"模板可以在同一个*编译单元*中扩展,而不是相同的文件.Scala编译器的编译单元等于文件的事实是一个实现细节.可能有其他编译器使用例如数据库来存储源工件而不是文件系统. (2认同)