一、概念
- 用来表示受限的类继承结构:当一个值为有限的几种类型,而不能有任何其它类型时。
- 由于编译器知道一共有几种类型,可用来优化 when 对分支的判断:
- 后期新增类型,却忘记修改 when 分支,最后走了 else 默认情况。(译器会提醒未穷举不给通过)。
- 很明确只存在几种情况,却为了满足编译器的要求写无效分支。(不必再写 else 默认分支)。
- 声明一个密封类使用 sealed 关键字,它是抽象类,造函数默认是 protected 可指定为 private。
- 当子类没有指定构造和属性时应该定义成 object,因为即便创建多个实例相互之间没有状态区别,编译器会提示 “ sealed' subclass has no state and no overridden 'equals() ”。在 Kotlin v1.9 版本新增了 data object 用于取代 object 的用法,编译器会提示“'sealed' sub-object can be converted to 'data object' ”,toString() 不会打印 HashCode 等无用信息让输出更有意义。
sealed class Language {
//定义在同一类中
data object English : Language()
data class French(val str: String) : Language()
class German(str: String) : Language()
}
//定义在同一文件中
data object Chinese : Language()
data class Japanese(val str: String) : Language()
class Korean(str: String) : Language()
fun demo(language: Language) {
when (language) {
//单例唯一直接判断实例,定义在类中需要指定外部类
Language.English -> TODO()
is Language.French -> TODO()
is Language.German -> TODO()
Chinese -> TODO()
is Japanese -> TODO()
is Korean -> TODO()
}
}
二、与枚举类的区别
enum只是一个值(常量),seald可以是一个值(定义成 data object 不携带数据),还可以是一个有状态的值(定义成 data class 携带数据)。
enum 更在意类型 | seald 更在意数据 | |
创建实例 | 每个常量都是单例,是枚举类的实例 | 子类可以有多个自己的实例 |
构造传参 | 常量形参跟enum一样 | 子类构造可以有参可以无参 |
属性 | 无 | 子类可以有各自的成员属性实现更多功能 |
函数 | 只能重写枚举类的函数 | 可以自定义函数 |
三、版本说明
Kotlin v1.0:直接子类必须是密封类的内部类。
Kotlin v1.1:直接子类必须跟密封类在同一文件中,间接子类可以在不同文件中。
Kotlin v1.5:直接子类必须跟父类在同一个 Gradle Module 且同一包名下(避免文件过大并限制类的扩展)。增加了密封接口。
四、密封接口
继承起来,接口比类更灵活,又有助于实现多类型层级嵌套。
语言 | 中文 | 普通话 |
上海话 | ||
四川话 | ||
英文 | 美国 | |
印度 | ||
新加坡 |
4.1 密封接口 + 密封接口
sealed interface Language
sealed interface Chinese : Language
object PuTongHua : Chinese
object ShangHaiHua : Chinese
object SiChuanHua : Chinese
sealed interface English : Language
object America : English
object India : English
object Singapore : English
//使用
fun demo(language: Language) {
when (language) {
is Chinese -> {
when (language) {
PuTongHua -> TODO()
ShangHaiHua -> TODO()
SiChuanHua -> TODO()
}
}
is English -> {
when (language) {
America -> TODO()
India -> TODO()
Singapore -> TODO()
}
}
}
}
4.2 密封接口 + 枚举类
sealed interface Language
enum class Chinese : Language{
PuTongHua, ShangHaiHua, SiChuanHua
}
enum class English : Language{
America, India, Singapore
}
fun demo(language: Language) {
when (language) {
is Chinese -> {
when (language) {
Chinese.PuTongHua -> TODO()
Chinese.ShangHaiHua -> TODO()
Chinese.SiChuanHua -> TODO()
}
}
is English -> {
when (language) {
English.America -> TODO()
English.India -> TODO()
English.Singapore -> TODO()
}
}
}
}