Kotlin中用于参数的通配符泛型

3

我有一个抽象类用于监听API回调,如下所示。ApiRs是每个API响应对象都继承自它的父对象。

abstract class ApiCallback<in T : ApiRs> {

    open fun onSucceed(apiRsModel: T) {}

    open fun onFailed(code: Int,
                      message: String) {
    }
}

我还编写了一个函数,在请求API之前检查网络状态,如果网络未连接,则会触发onFailed

fun isNetworkAvailable(apiCallback: ApiCallback<ApiRs>?,
                           context: Context): Boolean{
        val connectivityManager = context
                .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val networkInfo = connectivityManager.activeNetworkInfo

        // device network unreachable
        if (networkInfo == null
                || !networkInfo.isConnected) {
            // callback with network error
            apiCallback?.onFailed(code, message)
            return false
        }

        return true
    }

参数类型ApiCallback<ApiRs>?实际上应该写成ApiCallback<? extends ApiRs>?,但是Kotlin中没有通配符。如果将泛型替换为ApiCallback<out ApiRs>?,它会显示一个错误。

投影与ApiCallback的相应类型参数的变化冲突

有什么方法可以解决这个问题吗?还是我对Kotlin泛型的概念有误?


2017/09/18更新 - 正确的方式是:

方法:

fun <T : ApiRs> isNetworkAvailable(apiCallback: ApiCallback<T>?,
                                       context: Context): Boolean {
        val connectivityManager = context
                .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val networkInfo = connectivityManager.activeNetworkInfo

        // device network unreachable
        if (networkInfo == null
                || !networkInfo.isConnected) {
            // callback with network error
            callbackWithFailed(
                    apiCallback,
                    ApiError.API_ERROR_CODE_0,
                    context.getString(R.string.api_error_code_0))
            return false
        }

        return true
    }

ApiCallback<out ApiRs> 可以接收任何类型的 ApiRs。请参阅星投影 https://kotlinlang.org/docs/reference/generics.html#star-projections。 - Nikola Despotoski
无法工作,当我使用 ApiCallback<out ApiRs> 时,上面会显示警告。 - Ivan
@NikolaDespotoski 是正确的。每个扩展 ApiRs 的 API 都将被接受,但是如果没有其他转换,它们只会具有您的 ApiRs 类提供的功能。 - creativecreatorormaybenot
好的,我知道你们的意思了,把 ApiCallback<ApiRs>? 改成 ApiCallback<*>? 对吧? - Ivan
不,ApiCallback<*>ApiCallback<Any>相同,您需要设置类型上限为ApiCallback<out SpecificType> - Nikola Despotoski
1个回答

3

我了解您想以一种方式接受 apiCallback:ApiCallback<ApiRs>?在您的方法中,使 ApiCallback 的通用类型可以是 ApiRs 本身或其任何子类型。 Kotlin有上限约束,而不是通配符。您可以这样声明函数:

fun <T: ApiRs> isNetworkAvailable(apiCallback: ApiCallback<T>?,
                       context: Context)

谢谢!你的解决方案非常有道理! - Ivan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接