为什么我们需要在网络响应中<出 T>



我用

标记了这个网络响应类
sealed class NetworkResponse<out T> {
data class Success<T>(val value: T): NetworkResponse<T>()
data class GenericError(val code: Int? = null, val error: String? = null): NetworkResponse<Nothing>()
object NetworkError: NetworkResponse<Nothing>()
class UnknownError(message: String? = "Unknown Error") : NetworkResponse<Nothing>()
}

如果我删除"out "用"T"接下来的课程开始失败。有人能解释一下为什么我们需要&;out &;(协变)在上面的代码指针,为什么下面的代码失败?

suspend fun <T> call(dispatcher: CoroutineDispatcher, apiCall: suspend () -> Response<T>): NetworkResponse<T> {
return withContext(dispatcher) {
try {
val data = apiCall.invoke()
if (data.isSuccessful) {
data.body()?.let { NetworkResponse.Success(it) } ?: NetworkResponse.UnknownError()
} else {
NetworkResponse.NetworkError
}
} catch (throwable: Throwable) {
when (throwable) {
is IOException -> {
Log.e("IOException", throwable.message?:"")
NetworkResponse.NetworkError
}
is HttpException -> {
Log.e("HttpException", throwable.message?:"")
val code = throwable.code()
val errorResponse = throwable.message()
NetworkResponse.GenericError(code, errorResponse)
}
else -> {
Log.e("GenericException", throwable.message?:"")
NetworkResponse.GenericError(null, null)
}
}
}
}
}

NetworkResponse<Nothing>NetworkResponse<out T>的子类型,而不是NetworkResponse<T>的子类型。如果你从逻辑上考虑所有的可能性,那就说得通了。

这允许NetworkResponse的错误子类型是单例objects或更灵活的数据类,不受类型的约束。

例如,NetworkError没有可以从中检索的T数据,因此无论T是什么,它都可以作为NetworkResponse的子类型,因为无论如何您都不会从中提取T。因此,NetworkError的单个实例是任何类型的有效NetworkResponse。

从概念上讲,您可以将Nothing类型视为所有类型的子类型,就像您可以将Any类型视为所有类型的超类型一样。

相关内容

  • 没有找到相关文章

最新更新