• 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)
    }

  • 相关阅读:
    java反射
    Java程序设计2023-第三次上机测试
    thinkphp6 入门教程合集(更新中)
    基于Java毕业设计影音娱乐销售管理系统源码+系统+mysql+lw文档+部署软件
    Reactor 第十二篇 WebFlux集成PostgreSQL
    [1Panel]开源,现代化,新一代的 Linux 服务器运维管理面板
    STL vector的操作
    通过cri-o部署k8s集群环境
    HTML静态页面获取url参数和UserAgent
    山水之城南京:OLED透明拼接屏技术的应用之旅
  • 原文地址:https://blog.csdn.net/sunny2come/article/details/126384893