一、核心特性与设计哲学
-
封闭的继承体系
-
密封类的所有直接子类必须在同一模块内声明(Kotlin 1.1 后放宽到同模块,此前需同文件)。
-
构造函数默认私有化,禁止外部继承,确保子类集合在编译时完全已知。
-
-
编译时类型安全
-
在
when表达式中处理密封类时,编译器强制检查是否覆盖所有子类,若遗漏则报错,无需else分支。 -
例如:
sealed class Result { data class Success(val data: String) : Result() data class Error(val msg: String) : Result() } fun handle(result: Result) = when(result) { is Success -> println(result.data) is Error -> println(result.msg) // 无 else,编译器确保穷尽 }
-
-
子类形式的灵活性
-
子类可以是
object(单例)、data class(携带数据)或普通类,支持异构数据结构sealed class Shape { object Circle : Shape() data class Rectangle(val w: Int, val h: Int) : Shape() }
-
二、底层实现机制
-
字节码转换
-
密封类编译为抽象类,子类转为静态内部类,构造函数私有化。
-
示例字节码伪代码:
public abstract class Shape { private Shape() {} // 私有构造 public static final class Circle extends Shape { /* 单例 */ } public static final class Rectangle extends Shape { /* 数据字段 */ } }
-
-
模式匹配优化
-
when表达式编译为instanceof链或switch语句(若子类可映射为整数)。 -
若未覆盖所有子类,编译器注入
throw NoWhenBranchMatchedException。
-
三、典型应用场景
-
状态机与 UI 状态管理
-
封装网络请求状态(加载/成功/错误),避免
null和非法状态sealed class UIState { object Loading : UIState() data class Success(val data: List<String>) : UIState() data class Error(val message: String) : UIState() }
-
-
替代枚举的增强方案
-
当各类型需携带不同数据时(如几何图形计算),密封类比枚举更灵活
fun area(shape: Shape): Double = when(shape) { is Circle -> π * shape.radius.pow(2) is Rectangle -> shape.width * shape.height }
-
-
设计模式实现
-
状态模式:封装不同状态的行为
sealed class State { abstract fun handle() object Idle : State() { override fun handle() = /* ... */ } object Active : State() { override fun handle() = /* ... */ } } -
访问者模式:通过子类分发处理逻辑。
-
四、与枚举类的对比
|
特性 |
密封类 |
枚举类 |
|---|---|---|
|
数据类型 |
子类可携带异构数据 |
所有实例类型一致 |
|
行为扩展 |
子类可自定义方法 |
共享统一方法 |
|
适用场景 |
需数据关联的复杂状态(如 API 响应) |
简单常量集合(如颜色类型) |
enum class Color { RED, GREEN } // 简单常量 sealed class ApiResult { // 复杂数据 data class Success(val json: String) : ApiResult() object Timeout : ApiResult() }
五、局限性
-
模块内封闭性
-
子类无法跨模块扩展,新增类型需修改原文件。
-
-
文件膨胀风险
-
大量子类集中同一文件可能降低可读性。
-
-
不支持多重继承
-
子类不能同时继承多个密封类(可用
sealed interface补充)。
-
总结
密封类通过编译时穷尽性检查和灵活的子类数据承载能力,成为 Kotlin 中建模有限状态(如 UI 状态、操作结果)的核心工具。其设计平衡了类型安全与扩展性,尤其适合替代枚举处理需携带异构数据的场景,但需注意模块封闭性带来的维护成本。
1622

被折叠的 条评论
为什么被折叠?



