组合 When 子句在 Kotlin 中给我带来了奇怪的错误

Combining When clauses gives me weird error in Kotlin

下面的 Kotlin 代码工作正常

 private inline fun <reified T> parseResponse(response: Any): Response<T> =
        when (response) {
            is T -> { Response(success = response, error = null) }
            is GetUserInfoResponseResult.Error -> {
                Response(
                    success = null,
                    error = Error(response.error.message ?: "", response.error.code?.name ?: "")
                )
            }
            is SetUserInfoResponseResult.Error -> {
                Response(
                    success = null,
                    error = Error(response.error.message ?: "", response.error.code?.name ?: "")
                )
            }
            else -> throw exception("Failed to process response ")
        }

然而,当我尝试组合 2 个 when 子句时

 private inline fun <reified T> parseResponse(response: Any): Response<T> =
        when (response) {
            is T -> { Response(success = response, error = null) }
            is GetUserInfoResponseResult.Error, SetUserInfoResponseResult.Error -> {
                Response(
                    success = null,
                    error = Error(response.error.message ?: "", response.error.code?.name ?: "")
                )
            }
         
            else -> throw exception("Failed to process response ")
        }

在 intelliJ 中,SetuUserInfoResponseResult.Error 中的 Error 有一条红色下划线 说

classifier Error does not have a companion object and thus must be initialized here 

定义

sealed class GetUserInfoResponseResult {

    data class Error(val error: GetUserInfoErrorResponse) : GetUserInfoResponseResult()

    data class Success(val success: GetUserInfoSuccessResponse) : GetUserInfoResponseResult()

}

sealed class SetUserInfoResponseResult {

    data class Error(val error: SetUserInfoErrorResponse) : SetUserInfoResponseResult()

    object Success : SetUserInfoResponseResult()

}

您当前的 when 子句检查 response 是否是 GetUserInfoResponseResult.Error 的实例,或者 response 是否等于 SetUserInfoResponseResult.Error 的伴随对象。后半部分是相等性检查,因为你没有在它之前写 isSetUserInfoResponseResult.Error 没有伴生对象,因此出现错误。

添加 is 并不能解决所有问题。您尝试访问 response.error.message 时仍然存在错误。这是因为智能转换仅在您检查单一类型时才有效。由于您正在检查 2,因此 response 的 compile-time 类型不是智能转换,仍然是 Any.

您可以通过引入两种错误类型都实现的通用接口来解决此问题:

interface UserInfoErrorResponseResult {
    val error: UserInfoErrorResponse
}

interface UserInfoErrorResponse {
    val message: String?
    val code: ErrorCode? // I assume you have an ErrorCode class like this
}

然后你可以只检查一种类型 - is UserInfoErrorResponseResult - 智能转换就可以了:

 private inline fun <reified T> parseResponse(response: Any): Response<T> =
        when (response) {
            is T -> { Response(success = response, error = null) }
            is UserInfoErrorResponseResult -> {
                Response(
                    success = null,
                    error = Error(response.error.message ?: "", response.error.code?.name ?: "")
                )
            }
         
            else -> throw exception("Failed to process response ")
        }

这是一个示例,说明您的 类 在实现这些接口时的样子,并假设了 GetUserInfoErrorResponseSetUserInfoErrorResponse 的样子。

data class GetUserInfoErrorResponse(
    override val message: String?,
    override val code: ErrorCode?
): UserInfoErrorResponse

data class SetUserInfoErrorResponse(
    override val message: String?,
    override val code: ErrorCode?
): UserInfoErrorResponse

sealed class GetUserInfoResponseResult {

    data class Error(override val error: GetUserInfoErrorResponse) :
        GetUserInfoResponseResult(), UserInfoErrorResponseResult

    data class Success(val success: GetUserInfoSuccessResponse) : GetUserInfoResponseResult()

}

sealed class SetUserInfoResponseResult {

    data class Error(override val error: SetUserInfoErrorResponse) :
        SetUserInfoResponseResult(), UserInfoErrorResponseResult

    object Success : SetUserInfoResponseResult()

}

基本上,您只需将 override 添加到界面所需的所有内容中,它就可以正常工作。