组合When子句在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 ")
}

但是当我尝试组合两个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的编译时类型不是智能强制转换的,仍然是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添加到接口所需的所有内容中,它就应该工作了。

最新更新