IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Kotlin:关于Sealed密封类 -> 正文阅读

[移动开发]Kotlin:关于Sealed密封类

如果要在Java中列举,我们可能会用Enum,而在Kotlin中,除了Enum以外,还有一個更加强大的工具——Sealed Class。

Enum Class

在Kotlin中的枚举类可以写成:

enum class Size {
    S, M, L, XL
}

然后使用when來判断:

fun getLength(size: Size): Int {
    when (size) {
        Size.S -> return 10
        Size.M -> return 30
        Size.L -> return 50
        Size.XL -> return 100
    }
}

枚举类也可以自带参数:

enum class Color(val rgb: String) {
    RED("0xFF0000"),
    GREEN("0x00FF00"),
    BLUE("0x0000FF")
}

使用看看:

fun main(args: Array<String>) {

    val length = getLength(Size.XL)
    println("length=$length")
    // 100

    val hex = Color.RED.rgb
    println("hex=$hex")
    // 0xFF0000
    
    for (v in Size.values()){
        println(v)
    }
    // S
    // M
    // L
    // XL
}

大guy~94醬。

Sealed Class:Enum Class 2.0

來看看Sealed Class有什么特性吧!

首先,先创建一个名为Operationsealed class,加上execute()方法,來玩玩看:

sealed class Operation {
    class Add(val value: Int) : Operation()
    class Subtract(val value: Int) : Operation()
    class Multiply(val value: Int) : Operation()
    class Divide(val value: Int) : Operation()
}

fun execute(x: Int, op: Operation) = when (op) {
    is Operation.Add ->      x + op.value
    is Operation.Subtract -> x - op.value
    is Operation.Multiply -> x * op.value
    is Operation.Divide ->   x / op.value
}

fun main(args: Array<String>) {
    
    val result = execute(5, Operation.Subtract(3))
    println("result=$result")
    // result=2
    
}

sealed class是个很酷的class,以上面的代码为例:·类别中有4个class,分別是AddSubtractMultiplyDivide,而且

也只能有这4个class。什么意思呢?

让我们用execute()方法来测试看看Operation类别所有的枚举情況:

fun execute(x: Int, op: Operation) = when (op) {
    is Operation.Add ->      x + op.value
    is Operation.Subtract -> x - op.value
    is Operation.Multiply -> x * op.value
    is Operation.Divide ->   x / op.value
}

如果我们试图将其中一种枚举情況刪除:

fun execute(x: Int, op: Operation) = when (op) {
    is Operation.Add ->      x + op.value
    is Operation.Subtract -> x - op.value
    is Operation.Multiply -> x * op.value
    // delete this line
}

Compiler就会有森77的fu:

‘when’ expression must be exhaustive, add necessary ‘is Divide’ branch or ‘else’ branch instead

翻译:when表达式应该是全面性的,应该要包含「其它」情況

所以我们加入else代表其他未过滤的枚举情況,就可以解決这个警告:

fun execute(x: Int, op: Operation) = when (op) {
    is Operation.Add ->      x + op.value
    is Operation.Subtract -> x - op.value
    is Operation.Multiply -> x * op.value
    else -> x
}

也就是说,你可以在Sealed Class中定义所有可能的情況,而在搭配when的使用下,compiler会强迫我们得去注意到这些情況是否都有被处理到,是个非常贴心的设计。

想像一下今天我們要开个API给別人,他可能不会知道一个参数status的所有种类,但通过Sealed Class与when的组合,可以强迫这个API的使用者去了解所有的种类,并进行处理。

基本上一個Sealed Class的Subclass预设不带任何参数,它会是个object:

sealed class Operation {
    class Add(val value: Int) : Operation()
    class Subtract(val value: Int) : Operation()
    class Multiply(val value: Int) : Operation()
    class Divide(val value: Int) : Operation()
    object Increment : Operation()
    object Decrement : Operation()
}

fun execute(x: Int, op: Operation) = when (op) {
    is Operation.Add       -> x + op.value
    is Operation.Subtract  -> x - op.value
    is Operation.Multiply  -> x * op.value
    is Operation.Divide    -> x / op.value
    is Operation.Increment -> x + 1
    is Operation.Decrement -> x - 1
}

fun main(args: Array<String>) {
    
    val result = execute(5, Operation.Increment)
    println("result=$result")
    // result=6

}

注意到了吗?当搭配when做使用的時候,参数的Sealed Class subclass需要使用is判断,不带参数的Object不需要使用is判断

fun execute(x: Int, op: Operation) = when (op) {
    is Operation.Add       -> x + op.value
    is Operation.Subtract  -> x - op.value
    is Operation.Multiply  -> x * op.value
    is Operation.Divide    -> x / op.value
    Operation.Increment -> x + 1
    Operation.Decrement -> x - 1
}

因为Kotlin中的Object就是最简单的单例模式,每个相同名称的Object其实都是一样的,也只会有这么一个。

Sealed class进阶应用

我们可以将要对View進行操作的功能封裝為一個sealed class(這邊為UiOp),並在裡面列舉出我們將會進行的動作:

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
}

覆寫「+」號運算符,提升程式碼的易讀性:

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

看一下使用範例:

val ui = Ui() +
        UiOp.Show +
        UiOp.TranslateX(20f) +
        UiOp.TranslateY(40f) +
        UiOp.Hide
 
run(view, ui)
fun run(view: View, ui: Ui) {
    ui.uiOps.forEach { execute(view, it) }
}

可以看到我们的方法run()就是对View進行操作。

进行什么操作呢?这些操作已经用非常易读的方式建构在ui变数了,藉由适时的使用sealed class,可以方便地让我们进行同一个系列的所有相关操作。

?参考文章:https://carterchen247.medium.com/kotlin使用心得-sealed-class-82eccf890ac0

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-09-25 23:17:16  更:2022-09-25 23:17:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 23:28:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码