密封类(Sealed Classes
)用来表示受限的类继承结构:当一个值的类型只能取自一个有限类型集合中的类型时。在某种程度上,密封类是枚举类的扩展:枚举类型的取值也是受限的,但是每个枚举常量只能有一个实例,而密封类的子类可以有多个实例并且可以包含状态。
声明一个密封类,要把sealed
修饰符放在类名的前面。密封类可以有子类,但是子类必须声明在和密封类相同的文件中。
sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()
- 密封类默认是抽象的,它无法被直接实例化,能拥有抽象成员。
- 密封类不允许有非
private
的构造函数,它的构造函数默认是private
的。 - 注意继承密封类子类的类可以放在任何地方,不必限于在同一个文件中。
密封类的关键好处在于当使用when
表达式的时候。如果能确认语句覆盖了所有情况,就不必使用else
语句。然而,这只有在when作为表达式(使用结果)而不是作为语句使用的时候才起作用。
fun eval(expr: Expr): Double = when(expr) {
is Const -> expr.number
is Sum -> eval(expr.e1) + eval(expr.e2)
NotANumber -> Double.NaN
// the `else` clause is not required because we've covered all the cases
}