组合 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
的伴随对象。后半部分是相等性检查,因为你没有在它之前写 is
。 SetUserInfoResponseResult.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 ")
}
这是一个示例,说明您的 类 在实现这些接口时的样子,并假设了 GetUserInfoErrorResponse
和 SetUserInfoErrorResponse
的样子。
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
添加到界面所需的所有内容中,它就可以正常工作。
下面的 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
的伴随对象。后半部分是相等性检查,因为你没有在它之前写 is
。 SetUserInfoResponseResult.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 ")
}
这是一个示例,说明您的 类 在实现这些接口时的样子,并假设了 GetUserInfoErrorResponse
和 SetUserInfoErrorResponse
的样子。
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
添加到界面所需的所有内容中,它就可以正常工作。