对比Java学Kotlin密封类
Posted 陈蒙_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对比Java学Kotlin密封类相关的知识,希望对你有一定的参考价值。
什么是密封类?
在 Kotlin 中类修饰符除了 open、abstract、data 这些,还有一个 sealed:
sealed interface Error // 注意,sealed 在 Kotlin 1.5 版本后才支持修饰 interface
sealed class IOError: Error {
constructor() { /*...*/ } // protected by default
private constructor(description: String): this() { /*...*/ } // private is OK
// public constructor(code: Int): this() {} // Error: public and internal are not allowed
}
class FileReadError(val f: File): IOError {}
open class DatabaseError(val db: DataSource): IOError {}
object RuntimeError: Error
首先密封类是类(或接口,以下统称为类),但是比普通的类多了一些限制,主要表现在继承关系上:
- 密封类的直接子类必须要跟父类在同一个包内,具体形式可以是在 top-level 的单个文件,也可以是嵌套类;
- 密封类的子类类型在编译时就已经完全确定,密封类所在包之外的使用方无法继承密封类新建其他的子类,对于密封类的孙子类则没有这个限制;
- 密封类的子类的可见性修饰符跟普通类没有区别;
- 同时,密封类天生是 abstract 的,里面可以有 abstract 方法,同时遵循抽象类的约束无法直接创建实例;
- 密封类可以有构造函数,但是构造函数的修饰符只能是 private 或 protected;
有什么作用?
由于密封类所有的子类型都是已知的,所以密封类一般用在“状态机”场景中,比如枚举错误类型、网络请求的结果类型、列表中的数据类型等。
特别是跟 when 关键字结合使用,口味更加哦,因为:
- 由于所有子类型已知,无需 else 分支:
fun log(e: Error) {
when (e) {
is FileReadError -> println("FileReadError")
is DatabaseError -> println("DatabaseError")
is RuntimeError -> println("RuntimeError")
}
}
- 一旦密封类的子类有所变更,IDE 里面的 when 表达式会立即提示,非常人性化:
‘when’ expression on sealed classes is recommended to be exhaustive, add ‘is NetworkResultError’ branch or ‘else’ branch instead
当然,在实际使用过程中,我们也可以实现层级更复杂的密封类:
与枚举的区别
看起来是不是跟枚举有点像?确实如此,甚至从某种程度上我们可以称密封类为加强版的枚举。
但是每种枚举只能有一个实例,但是密封类没有这个限制。
参考文档
以上是关于对比Java学Kotlin密封类的主要内容,如果未能解决你的问题,请参考以下文章