栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【对比Java学Kotlin】密封类

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【对比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

当然,在实际使用过程中,我们也可以实现层级更复杂的密封类:

 
与枚举的区别 

看起来是不是跟枚举有点像?确实如此,甚至从某种程度上我们可以称密封类为加强版的枚举。
但是每种枚举只能有一个实例,但是密封类没有这个限制。

参考文档
  • Sealed classes
  • Sealed classes - Kotlin Vocabulary
  • KotlinConf 2018-Sealed Class Opened My Mind
  • Sealed Classes in Kotlin
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/294891.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号