Kotlin – Sealed Classes


  如果有一个接口类interface Expr,其有两个实现:

interface Expr
class Num(val value: Int) : Expr class Sum(val left: Expr, val right: Expr) : Expr

  当你用when表达式处理的时候,必须有else分支来作为默认选择:

fun eval(e: Expr): Int =
        when (e) {

            is Num -> e.value
            is Sum -> eval(e.left) + eval(e.right)
            else -> throw  IllegalArgumentException("Unknown expression")
        }

  如果此时再实现一个interface Expr的类class A,编译器不会强制要求你在when中新增分支来检测,如果你忘记增加新的分支来处理这个类,默认的else分支将会被选择,那就有可能会在这里出现BUG。
  避免这一问题的方法就是使用sealed class:

sealed class Expr {
 class Num(val value: Int) : Expr() class Sum(val left: Expr, val right: Expr) : Expr() } fun eval(e: Expr): Int = when (e) { is Expr.Num -> e.value is Expr.Sum -> eval(e.left) + eval(e.right) }

  将超类标记为sealed,其所有子类必须作为nested class在超类中声明。此时当你使用when时,就不需要使用else分支了,因为此时所有的可能就是超类的所有子类,不会再出现其他情况。
  sealed class不能被定义在其外部的类继承,其构造函数是private的,只能在内部被其子类调用。所以也无法声明一个sealed interface
  目前来说,sealed的功能受很大的限制,比如说其所有子类必须是nested,也不能被作为一个data class使用。