Scala的密封抽象与抽象类


Answers:


90

区别在于,密封类的所有子类(无论是否抽象)都必须与密封类位于同一文件中。


34
不太明显的一点(至少对我来说不是这样:-))是密封类的“大孩子”也可以放在其他文件中:给定密封类A;B延伸A; C扩展了B。B必须与A在同一个文件中,但是C可以保留在同一个文件中或另一个文件中。
Sandor Murakozi 2010年

7
@SandorMurakozi如果要实现B,也必须将B声明为密封类。密封仅处理直接继承。
natbusa 2014年

77

回答所示,密封类的所有直接继承的子类(是否抽象)都必须在同一文件中。这样做的实际后果是,如果模式匹配不完整,则编译器可以发出警告。例如:

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
}

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


1
如果没有sealed关键字,为什么编译器不能推断出模式匹配不完整?
sasha.sochka

7
@ sasha.sochka假设我将其编译并放入没有sealed关键字的jar文件中。到此为止,所有内容都已编译,包括match语句。现在,另一个用户抓住了这个jar并进行了扩展Tree。没有什么可以阻止他这样做的,但是到那时,match声明不再完整。由于他没有编译它,只是从您的jar中使用它,因此编译器无法警告。而且由于创建罐子时您并不知道它,所以它无法警告您。
Daniel C. Sobral 2014年

@DanielCSobral,你写“但在一点上,匹配语句不再完整。” 在制作jar文件之前,编译您发布的原始代码(但没有关键字)时,match语句此时是否不完整sealed?看起来很容易推断,因为即使没有新的孩子(编译器尚不了解他们),也没有分支Empty。我说的是警告创建瓶子的人,而不是警告使用它的人。
sasha.sochka 2014年

1
@ sasha.sochka好吧,我想它可能会警告说它Empty丢失了,但是重点是,即使您添加Empty,它也可能是不完整的,取决于是否在单独的编译中发生了什么。
Daniel C. Sobral 2014年

是的,那我同意你的看法。
sasha.sochka 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.