sealed class在Kotlin中是一种抽象类,限制了子类型的层次结构:所有子类型必须在同一个文件中声明。这对于选项集固定的层次结构(例如,用于描述状态、事件或错误)非常方便:
sealed class Result { object Success : Result() data class Error(val message: String) : Result() object Loading : Result() } fun handle(result: Result) = when (result) { is Result.Success -> print("成功!") is Result.Error -> println("错误:${result.message}") is Result.Loading -> println("加载中...") }
与when的关系:
如果我们在when表达式中使用所有sealed class的子类型,编译器会检查穷尽性(exhaustiveness)。这保证了当添加新状态时,开发者如果不处理新选项就会收到编译错误。
为什么需要这个:
"可以将sealed class的子类放在不同的文件或包中吗?这对类型安全有什么影响?"
**答案:**不可以,所有sealed class的直接子类必须在同一个文件中定义。这是编译器对类型安全保证的控制。如果在其他文件包中放置子类,编译器会报错。
故事
在设计支付业务逻辑时,添加了操作结果的选项,忘记更新when表达式。不过由于sealed class,编译器高亮了未考虑的情况。在另一个Java项目中,这种情景会导致未初始化的状态进入产品。
故事
在项目中,将部分数据的sealed class迁移到普通的open class后,exhaustive when检查不再有效,新状态开始在处理逻辑中“丢失”,导致界面行为不正确。
故事
在电子商务系统中,试图通过将sealed class的子类移到单独的文件(每个文件在自己的模块中以便重用)来优化架构。这破坏了编译并导致在发布前进行紧急重构。