Kotlin 密封类,密封类用于表示受限类层次结构,其中对象或值可以具有来自有限值集合的类型之一。您可以将密封类视为枚举类的扩展。枚举类中的值集也受到限制,但枚举常量只能有单个实例,而密封类的子类可以有多个实例。
为什么我们需要密封类
让我们首先了解密封类的必要性。在下面的例子中,我们有一个类Color
,它有三个子类Red
,Orange
和Blue
。
这里的eval()
方法中的when
表达式必须使用else
分支,否则我们会得到一个编译错误。现在,如果我们尝试向类Color
添加子类,则else
分支中的代码将执行,这是默认代码。编译器应警告我们新添加的子类的代码不存在,因此我们应该在添加新子类,而不在表达式中添加逻辑时收到警告或错误。使用Sealed
类解决了这个问题。
open class Color{
class Red : Color()
class Orange : Color()
class Blue : Color()
}
fun eval(c: Color) =
when (c) {
is Color.Red -> println("Paint in Red Color")
is Color.Orange -> println("Paint in Orange Color")
is Color.Blue -> println("Paint in Blue Color")
else -> println("Paint in any Color")
}
fun main(args: Array<String>) {
val r = Color.Red()
eval(r)
}
Kotlin 密封类示例
在 Kotlin 中,在类标题中的class
关键字之前使用sealed
关键字声明了密封类。
让我们使用密封类在上面看到的相同示例。这里我们通过将类Color
标记为密封来解决上述问题。
名称密封的类仅表示从一组有限的值中获取值。这里else
分支在when
表达式中不是必需的,因为编译器知道该类是密封的,它只需要三个派生类的表达式,不需要默认的else
分支。现在,如果我们尝试将新的子类添加到类Color
中,它将不会创建不必要的错误,而是会引发错误。
例如,如果我们在密封类Color
中添加一个新的子类White
,并且在表达式时不添加White
子类的表达式,那么我们将得到此错误 – Error:(12, 9) Kotlin: 'when' expression must be exhaustive, add necessary 'is White' branch or 'else' branch instead
sealed class Color{
class Red : Color()
class Orange : Color()
class Blue : Color()
}
fun eval(c: Color) =
when (c) {
is Color.Red -> println("Paint in Red Color")
is Color.Orange -> println("Paint in Orange Color")
is Color.Blue -> println("Paint in Blue Color")
}
fun main(args: Array<String>) {
val r = Color.Red()
eval(r)
}
输出:
现在你可以理解,通过使类密封,我们将限制添加到类层次结构中。
Kotlin 的密封类规则
- 我们无法创建密封类的对象,这意味着密封类无法实例化。
- 密封类的所有子类必须在声明密封类的同一文件中声明。
- 密封类的构造函数默认为
private
,我们不能将其设为非私有。