sealed class 和 sealed interface 是 Kotlin 中受限类型层次结构的机制,所有可能的子类在编译阶段都是已知的。与普通抽象类不同,sealed class 保证在 when 表达式中对所有变体进行穷尽处理。根据 JetBrains Kotlin Language Guide (2026) 文档,sealed 类型是 Kotlin 项目中状态建模、UI 屏幕和结果类型的基础。
要点
sealed class 是一个带有限制的抽象类:其所有直接子类必须与 sealed class 在同一文件中声明。这个限制使层次结构封闭(sealed)——文件外部的任何代码都不能添加新的子类。
sealed interface 在 Kotlin 1.5 中添加,提供了相同的保证,但具有接口的灵活性:sealed interface 可以在一个文件中由多个类、对象或其他接口实现。与 sealed class 不同,sealed interface 没有单继承的限制——一个类可以同时实现多个 sealed 接口。
根据 Kotlin Evolution and Roadmap (2026),sealed interface 是应社区要求添加的,以实现更灵活的建模。主要动机是在没有多重类继承的情况下组合独立的类型层次结构。
sealed class 的声明以 class 前的 sealed 修饰符开始。子类在同一文件中声明。
sealed class NetworkResult {
data class Success(val data: String) : NetworkResult()
data class Error(val message: String) : NetworkResult()
object Loading : NetworkResult()
}
每个 sealed class 的子类可以有自己的属性和方法。Loading 是一个单例(object),Success 和 Error 是带参数的 data class。编译器知道所有三个变体,并在使用 when 时检查它们的完整性。
sealed 类可以嵌套,为复杂数据模型创建多级层次结构,而不会丢失类型安全。
sealed class UiState {
object Idle : UiState()
object Loading : UiState()
data class Content(val items: List<Item>) : UiState()
data class Error(val exception: Throwable) : UiState()
}
sealed interface 的声明类似于 sealed class,但允许在一个类中实现多个 sealed 接口。
sealed interface Action
sealed interface Loggable
data class Navigate(val route: String) : Action, Loggable
data class ShowToast(val text: String) : Action
object GoBack : Action, Loggable
Navigate 类同时实现了两个 sealed 接口——Action 和 Loggable。对于 sealed class,由于单继承的限制这是不可能的。sealed interface 提供了组合独立层次结构的灵活性。
sealed interface 在层次结构不需要共享状态或构造函数时更为优选。根据 JetBrains Kotlin Guidelines (2026),对于所有不需要公共构造函数的新层次结构,应默认使用 sealed interface,这使得代码对未来扩展更加灵活。
sealed 类型的主要优势是在 when 表达式中的穷尽(exhaustive)处理。编译器检查所有可能的子类是否都已考虑。
fun handleResult(result: NetworkResult): String = when (result) {
is NetworkResult.Success -> "Data: ${result.data}"
is NetworkResult.Error -> "Error: ${result.message}"
is NetworkResult.Loading -> "Loading..."
// else 不是必需的 — 编译器知道所有变体都已涵盖
}
如果开发者向 sealed 层次结构添加新子类但忘记在 when 中处理它——编译器将报错。这是类型级别的安全性,在使用带 else 分支的开放层次结构时不可用。
根据 Google Android Developers (2026),sealed 类是在 Jetpack Compose 中建模 UI 状态的推荐方式。when 的穷尽检查防止了开发者未处理所有可能屏幕显示变体的情况。
enum class 和 sealed class 经常被混淆,但它们的用途和能力不同。
| 特性 | sealed class | enum class |
|---|---|---|
| 实例 | 多个(data class),一个(object) | 每个常量恰好一个 |
| 属性 | 每个子类不同 | 所有常量相同 |
| 继承 | 是(从 sealed class) | 否(implicit final) |
| 构造函数 | 可以有参数 | 仅所有常量共享 |
| 层次结构 | 受限,sealed | 固定常量集 |
选择 sealed class 和 enum class 取决于任务。如果变体不携带额外数据——使用 enum。如果每个变体包含唯一字段——使用 sealed class 或 sealed interface。
sealed 类型在 Kotlin 项目中用于一系列需要类型安全建模的标准场景。
每个 Compose 屏幕可以有一个 sealed class UiState 来描述所有可能的状态:Idle、Loading、Content(data)、Error(exception)。when 表达式保证所有状态都被处理。
NetworkResult 带有 Success、Error、Loading 变体——使用 Retrofit 和 Ktor 的 Kotlin 项目中的标准模式。sealed class 确保安全地处理每个请求结果。
sealed interface 用于导航路由,允许模块在统一层次结构内声明自己的路由。这消除了编译阶段未知路由的错误。
根据 KotlinConf (2025),sealed class 和 sealed interface 是现代 Kotlin 应用程序中类型安全设计的基础。它们与 data class 结合使用,用于建模复杂领域结构,而不会在编译阶段失去安全性。
常见问题
所有 sealed class 的直接子类必须在同一文件中声明。对于 sealed interface 也是同样的规则——实现在一个文件中。
不,单文件规则同样适用于 sealed interface。所有实现必须在声明 sealed interface 的文件中。
sealed interface 没有状态和构造函数,允许多重实现。sealed class 可以有构造函数和共享状态,但一个类只能继承一个 sealed class。
编译器检查 when 的完整性:如果没有处理所有子类,代码将无法编译。这消除了运行时错误并使代码更安全。
可以,sealed class 可以有构造函数(默认为 private)。所有子类可以通过 super() 向此构造函数传递参数。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。