Kotlin Sealed Class

Sealed Classes 是什么?
我们先来看一下官方对 Sealed Classes 的解释

我们将上面这段话,简单的总结一下:

Sealed Classes 用于表示受限制的类层次结构
从某种意义上说,Sealed Classes 是枚举类的扩展
枚举的不同之处在于,每个枚举常量仅作为单个实例存在,而 Sealed Classes 的子类可以表示不同状态的实例
那上面这三段话分别是什么意思呢?接下来我们围绕这三个方面来分析。

Sealed Classes 用于表示受限制的类层次结构
Sealed Classes 用于表示受限制的类层次结构,其实这句话可以拆成两句话来理解。

Sealed Classes 用于表示层级关系: 子类可以是任意的类, 数据类、Kotlin 对象、普通的类,甚至也可以是另一个 Sealed
Sealed Classes 受限制: 必须在同一文件中,或者在 Sealed Classes 类的内部中使用,在Kotlin 1.1 之前,规则更加严格,子类只能在 Sealed Classes 类的内部中使用
Sealed Classes 的用法也非常的简单,我们来看一下如何使用 Sealed Classes。

sealed class Color {
    class Red(val value: Int) : Color()
    class Green(val value: Int) : Color()
    class Blue(val name: String) : Color()
}

fun isInstance(color: Color) {
    when (color) {
        is Color.Red -> TODO()
        is Color.Green -> TODO()
        is Color.Blue -> TODO()
    }
}

在这里推荐大家一个快捷键 Mac/Win/Linux:Alt + Enter 可以补全 when 语句下的所有分支,效果如下所示:

更多 AndroidStudio 快捷键,可以看之前的两篇文章

为数不多的人知道的AndroidStudio快捷键(一)
为数不多的人知道的AndroidStudio快捷键(二)
Sealed Classes 是枚举类的扩展
从某种意义上说,Sealed Classes 是枚举类的扩展,其实 Sealed Classes 和枚举很像,我们先来看一个例子。

正如你所看到的,在 Sealed Classes 内部中,使用 object 声明时,我们可以重用它们,不需要每次创建一个新实例,当这样使用时候,它看起来和枚举非常相似。

注意:实际上很少有人会这么使用,而且也不建议这么用,因为在这种情况枚举比 Sealed Classes 更适合

在什么情况下使用枚举
如果你不需要多次实例化,也不需要不提供特殊行为,或者也不需要添加额外的信息,仅作为单个实例存在,这个时候使用枚举更加合适。

Sealed Classes 的子类可以表示不同状态的实例
与枚举的不同之处在于,每个枚举常量仅作为单个实例存在,而 Sealed Classes 的子类可以表示不同状态的实例,我们来看个例子可能更容易理解这句话。

这里我们延用之前在 Google 推荐在项目中使用 sealed 和 RemoteMediator 这篇文章中用到的例子,在请求网络的时候需要对成功或者失败进行处理,我们来看一下用 Sealed Classes 如何进行封装。

sealed class PokemonResult {
    data class Success(val value: T) : PokemonResult()

    data class Failure(val throwable: Throwable?) : PokemonResult()
}

这里只贴出来部分代码,核心实现可以查看项目 PokemonGo
GitHub 地址:https://github.com/hi-dhl/PokemonGo
代码路径:PokemonGo/app/…/com/hi/dhl/pokemon/data/remote/PokemonResult.kt

一起来看一下如何使用

when (result) {
    is PokemonResult.Failure -> {
        // 进行失败提示
    }
    is PokemonResult.Success -> {
        // 进行成功处理
    }
}

我们在来看另外一个例子,在一个列表中可能会有不同类型的数据,比如图片、文本等等,那么用 Sealed Classes 如何表示。

sealed class ListItem {
    class Text(val title: String, val content: String) : ListItem()
    class Image(val url: String) : ListItem()
}

这是两个比较常见的例子,当然 Sealed Classes 强大不止于此,还有更多场景,等着一起来挖掘。

我们来看一下大神 Antonio Leiva 在这篇文章 Sealed classes in Kotlin: enums with super-powers 分享的一个比较有趣的例子,对 View 进行的一系列操作可以封装在 Sealed Classes 中,我们来看一下会有什么样的效果。

sealed class UiOp {
    object Show: UiOp()
    object Hide: UiOp()
    class TranslateX(val px: Float): UiOp()
    class TranslateY(val px: Float): UiOp()
}

fun execute(view: View, op: UiOp) = when (op) {
    UiOp.Show -> view.visibility = View.VISIBLE
    UiOp.Hide -> view.visibility = View.GONE
    is UiOp.TranslateX -> view.translationX = op.px
    is UiOp.TranslateY -> view.translationY = op.px
}

在 Sealed Classes 类中,我们定义了一系列 View 的操作 Show 、 Hide 、 TranslateX 、 TranslateY ,现在我们创建一个类,将这些对视图的操作整合在一起。

class Ui(val uiOps: List = emptyList()) {
    operator fun plus(uiOp: UiOp) = Ui(uiOps + uiOp)
}

你可能感兴趣的:(android,kotlin,基础,kotlin,android,开发语言)