持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第31天,点击查看活动详情
前言
当我们想要确保给定类型的值只能来自特定的有限子类型集时,密封类很有用。换句话说,密封类用于表示受限类层次结构,当一个值可以具有有限集合中的一种类型,但不能具有任何其他类型时。密封类具有数量有限的直接子类,所有子类都定义在与密封类本身相同的文件中。
它们是抽象的。这意味着我们不能直接实例化密封类的实例,只能实例化声明的子类之一。
如何在 Kotlin 中创建密封类?
示例
新建一个类,在类前面加上sealed关键字,使其成为密封类。
sealed class Result
现在将两个子类直接添加到同一个文件中:
data class Success(val response : Response) : Result()
data class Failure(val exception : Exception) : Result()
所以Result.kt 文件将是
sealed class Result {
data class Success(val response : Response) : Result()
data class Failure(val exception : Exception) : Result()
}
使用密封类,我们可以简化与任何类相关的状态管理。让我们考虑处理三种状态的基本示例:加载、成功和失败。
sealed class Result {
data class Success(val response : Response) : Result()
data class Failure(val exception : Exception) : Result()
data class Loading(var loading : Boolean) : Result()
}
与枚举类不同,每个案例都是类的单个实例,我们可以有密封类的子类的多个实例。
data class Success(val response : Response) : Result()
现在我们将创建两个不同的 Success 实例。例如,我们可以将 responseA 作为参数传递给第一个实例,将 responseB 作为参数传递给第二个实例,然后进行比较。
Kotlin 允许我们在密封类中使用when表达式。当我们将这些与 Result 密封类一起使用时,我们可以根据结果是成功、失败还是加载来解析结果。
when (result) {
is Result.Success -> showData()
is Result.Failure -> showError()
is Result.Loading -> showLoader()
}
我们不能在声明它的文件之外创建密封类的直接子类,并且密封类的构造函数始终是私有的。这意味着如果我们在项目的另一个文件中定义了不同的类,我们不能扩展类 Result。它提供了有限数量的层次结构,使其成为私有的。因此,密封类的所有子类都必须声明在与密封类本身相同的包中。
结论
在本文中,我们了解了 Kotlin 的密封类如何以及为什么它们可能是状态管理的更好选择。