Kotlin的中 sealed class(密封类) 详细使用

7 阅读3分钟

一、先一句话讲清楚:密封类是啥?

密封类 = 受限制的类 + 加强版枚举

  • 它用来表示有限的、固定的、可枚举的类型
  • 比如:网络请求结果、页面事件、状态、操作类型...
  • 它的子类数量是固定的,不能随便加

核心作用:让类型更安全,when 表达式不用写 else!

二、超级通俗比喻

密封类就像手机的操作

  • 开机
  • 关机
  • 重启
  • 调节音量

就这几种,不会突然冒出一个 “炒菜” 操作。密封类就是把固定类型全部列出来,不允许乱加。

三、基础语法(最标准写法)

1. 定义密封类

kotlin

// 关键字:sealed class
sealed class Result {
    // 所有子类必须写在里面
    object Success : Result()       // 无参数
    object Loading : Result()        // 无参数
    data class Error(val msg: String) : Result() // 带参数
}

定义一个叫 Result 的 “结果家族”,里面只有 3 个成员,任何时候都只能是这 3 种结果之一,不能多也不能少。

表格

成员类型作用为啥这么写?
Successobject(单例)表示 “请求成功”成功只需要 1 个状态,不需要额外数据,用单例最省内存
Loadingobject(单例)表示 “加载中”加载中只是一个状态,不带数据,用 object 最合适
Errordata class(数据类)表示 “请求失败”失败必须带错误信息(msg),用 data class 自动存数据

2. 使用(when 表达式,最爽!)

kotlin

fun handleResult(result: Result) {
    when (result) {
        is Result.Success -> println("成功")
        is Result.Loading -> println("加载中")
        is Result.Error -> println("错误:${result.msg}")
        // 不用写 else!!!因为密封类子类是固定的
    }
}

3. 总结(背会这 3 句)

  1. sealed class = 固定成员的 “家族” ,所有子类必须在同一文件定义
  2. object = 无数据状态(Loading/Success),data class = 带数据状态(Error)
  3. when 表达式不用 else,编译器强制覆盖所有情况,类型安全

四、密封类两种子类写法(必掌握)

1. 无参数 → 用 object(单例)

kotlin

sealed class HomeIntent {
    object LoadData : HomeIntent()
    object RefreshData : HomeIntent()
}

使用:

kotlin

HomeIntent.LoadData

2. 带参数 → 用 data class

kotlin

sealed class HomeIntent {
    data class ItemClick(val position: Int) : HomeIntent()
}

使用:

kotlin

HomeIntent.ItemClick(5)

3. 完整用法:

1、在Activity中调用:

//1、调用
Utils.optionalFunction( HomeIntent.Success)
Utils.optionalFunction( HomeIntent.Loading)
Utils.optionalFunction( HomeIntent.ItemClick(5))

2、在Utils或ViewMOdel中使用:


object Utils {

    /***
     * 2、执行过程
     */
    fun optionalFunction(homeIntent: HomeIntent) {
        when (homeIntent) {
            is HomeIntent.Success -> {
                println("Operation successful")
            }
            is HomeIntent.Loading -> {
                println("Loading...")
            }
            is HomeIntent.ItemClick -> {
                println("Item clicked at position: ${homeIntent.position}")
            }
        }
    }
}

/***
 * 3、密封类
 */
sealed class HomeIntent {
    object Success : HomeIntent() // 无参数
    object Loading : HomeIntent() // 无参数
    data class ItemClick(val position: Int) : HomeIntent()// 带参数
}

五、密封类最常用的 3 大场景(实战)

场景 1:网络请求状态(最常用)

kotlin

sealed class NetResult<out T> {
    object Loading : NetResult<Nothing>()
    data class Success<T>(val data: T) : NetResult<T>()
    data class Error(val msg: String) : NetResult<Nothing>()
}

使用:

kotlin

when(netResult) {
    NetResult.Loading -> 显示加载
    is NetResult.Success -> 显示数据
    is NetResult.Error -> 显示错误
}

场景 2:MVI 架构页面事件(你刚才的代码)

kotlin

sealed class HomeIntent {
    object LoadData : HomeIntent()
    object RefreshData : HomeIntent()
    data class ItemClick(val pos: Int) : HomeIntent()
}

场景 3:页面状态 / 类型

kotlin

sealed class PageState {
    object Empty : PageState()
    object Content : PageState()
    object Error : PageState()
}

六、密封类 VS 枚举类(超级清晰)

表格

特性枚举 Enum密封类 Sealed Class
类型只能是常量可以是类、带参数
传参不能带复杂参数可以带任意参数
扩展性
适用简单类型(性别、状态)复杂类型、事件、结果

一句话:枚举是简单常量,密封类是带结构、带数据的类型。

七、密封类的 4 个核心特性(面试必背)

  1. 子类数量固定所有子类必须定义在密封类内部
  2. 构造方法私有不能随便实例化
  3. when 表达式不用 else编译器知道所有子类
  4. 支持带参数 + 无参数灵活度极高

八、最简单总结(背会这 4 句)

  1. sealed class 是密封类,用来表示固定类型
  2. 子类用 object(无参)或 data class(有参)
  3. when 表达式不用 else,类型安全
  4. 主要用于:网络结果、MVI 事件、页面状态