# Kotlin 密封类

> 原文： [https://www.programiz.com/kotlin-programming/sealed-class](https://www.programiz.com/kotlin-programming/sealed-class)

#### 在本文中，您将在示例的帮助下了解密封类，如何创建它们以及何时使用它们。

当值只能具有有限集合（受限制的层次结构）中的一种类型时，使用密封类。

* * *

在详细介绍密封类之前，让我们探讨它们解决的问题。 让我们举个例子（摘自 Kotlin 官方网站-[密封类](https://kotlinlang.org/docs/reference/sealed-classes.html)文章）：

```kt
class Expr
class Const(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr) : Expr

fun eval(e: Expr): Int =
        when (e) {
            is Const -> e.value
            is Sum -> eval(e.right) + eval(e.left)
            else ->
                throw IllegalArgumentException("Unknown expression")
        }
```

在上述程序中，基类`Expr`具有两个派生类`Const`（代表一个数字）和`sum`（代表两个表达式的总和）。 在这里，必须使用`else`分支作为`when`表达式的[默认条件](/kotlin-programming/when-expression "Kotlin when expression")。

现在，如果您从`Expr`类派生新的子类，则编译器将不会检测到任何东西，因为`else`分支对其进行处理会导致错误。 如果在添加新的子类时编译器发出错误，那就更好了。

要解决此问题，可以使用密封类。 如前所述，密封类限制了创建子类​​的可能性。 并且，当您在`when`表达式中处理密封类的所有子类时，不必使用`else`分支。

* * *

要创建密封类，请使用密封修饰符。 例如，

```kt
sealed class Expr
```

* * *

### 示例：密封类

使用密封类可以解决上述问题：

```kt
sealed class Expr
class Const(val value: Int) : Expr()
class Sum(val left: Expr, val right: Expr) : Expr()
object NotANumber : Expr()

fun eval(e: Expr): Int =
        when (e) {
            is Const -> e.value
            is Sum -> eval(e.right) + eval(e.left)
            NotANumber -> java.lang.Double.NaN
        }

```

如您所见，没有`else`分支。 如果您从`Expr`类派生新的子类，则除非该子类在`when`表达式中进行处理，否则编译器将抱怨。

* * *

### 几个重要说明

*   密封类的所有子类必须在声明了密封类的同一文件中声明。
*   密封类本身就是[抽象](https://www.programiz.com/kotlin-programming/abstract-class "Kotlin Abstract class")，您不能从中实例化对象。
*   您不能创建密封类的非私有构造器。 它们的构造器默认为`private`。

* * *

### 枚举与密封类之间的区别

*枚举类*和密封类非常相似。 枚举类型的值集也像密封类一样受到限制。

唯一的区别是，枚举只能有一个实例，而密封类的子类可以有多个实例。