Kotlin泛型密封类中when表达式返回类型判定规则咨询
Kotlin泛型密封类与when表达式的类型推导问题
问题背景
定义了两个泛型密封类:
sealed class UiState<out T: Any>{ data class Error<T: Any>(val errorMessage: String): UiState<T>() data class Success<T: Any>(val data: T): UiState<T>() }
sealed class Result<out T: Any>{ data class Success<T: Any>(val data: T): Result<T>() class Error(val exception: UseCaseException): Result<Nothing>() }
实现了转换函数:
fun convert(result: Result):UiState<result.data> = when(result) { is Result.Success -> UiState.Success(result.data) is Result.Error -> UiState.Error("An error has occurred.") }
疑问:
- 为何convert函数始终返回
UiState<result.data>? - 为何错误场景下不会被判定为需返回
UiState.Error<String>? - 推测:UiState的Error类未使用泛型T,因此整个UiState的类型由Success类决定,这是否是when表达式返回固定类型的原因?
核心原因解析
显式返回类型强制统一分支类型
你给convert函数显式指定了返回类型UiState<result.data>,Kotlin会强制所有when分支的返回值都适配这个类型,不会自动推导分支各自的类型再取共同父类。协变与Nothing类型的适配作用
Result.Error继承自Result<Nothing>,而UiState是协变(out T)的,Nothing是所有类型的子类型。因此UiState.Error会被自动推导为UiState<result.data>类型(因为协变允许子类类型的实例赋值给父类类型变量),自然不会出现UiState.Error<String>的情况。你的推测部分正确,但并非核心
UiState的Error类确实没用到泛型参数T,但更关键的是:
- 显式声明的返回类型锁死了整体返回类型,分支必须向这个类型对齐;
- 协变特性让
UiState.Error可以安全向上转型为UiState<result.data>,无需单独推导为UiState<String>。
如果想让错误分支返回UiState.Error<String>,可以去掉函数返回类型的显式声明,让Kotlin自动推导所有分支的共同父类型(此时UiState.Success<List<Name>>和UiState.Error<String>的共同父类是UiState<Any>)。或者调整UiState定义,让Error分支不依赖T——比如把UiState.Error改成非泛型类,继承自UiState<Nothing>,这样错误分支类型就是UiState<Nothing>,和成功分支的共同父类是UiState<out Any>。
内容的提问来源于stack exchange,提问作者ntos
相关产品推荐
相关产品推荐

