generics - 从泛型函数返回特定实例

标签 generics kotlin

我的问题是关于泛型方法的类型推断。

我有以下场景:

interface Obj {
    val Id: String
}
data class User(override val Id: String, val name: String): Obj
data class Case(override val Id: String, val subject: String): Obj

interface Api {
    fun <T: Obj> getLastUpdated(type: KClass<T>, backTill: Duration = Duration.ofDays(1)): LastUpdated

    fun <T: Obj> getDetails(type: KClass<T>, uuid: String): Details<T>

    data class LastUpdatedResponse(val ids: List<String> = emptyList(),
                                   val latestDateCovered: String = "")
    data class LastUpdated(val error: Throwable? = null, val response: LastUpdatedResponse? = null)

    data class DetailsResponse<T>(val wrapped: T)
    data class Details<T>(val error: Throwable? = null, val response: DetailsResponse<T>? = null)
}

在我的测试中,我需要确切地知道模拟的 API 需要返回什么,因此

val testCase = Case("123", "Testing")
val testUser = User("321", "Dummy")
val mockApi = object: Api {
    override fun <T : Obj> getLastUpdated(type: KClass<T>, backTill: Duration): Api.LastUpdated {
        return Api.LastUpdated(response = Api.LastUpdatedResponse(listOf("123")))
    }

    override fun <T : Obj> getDetails(type: KClass<T>, uuid: String): Details<T> {
        when (type) {
            Case::class -> return Api.Details(response = Api.DetailsResponse(wrapped = testCase)) // <- this fails
            User::class -> return Api.Details(response = Api.DetailsResponse(wrapped = testUser)) // <- as does this
            else -> return Api.Details(error = UnsupportedOperationException())
        }
    }
}

但是,这无法编译:

Error:(114, 43) Kotlin: Type inference failed. Expected type mismatch: inferred type is Api.Details<Case> but Api.Details<T> was expected

我可以通过强制转换使其工作:

when (type) {
    Case::class -> return Api.Details(response = Api.DetailsResponse(wrapped = testCase)) as Api.Details<T>
    User::class -> return Api.Details(response = Api.DetailsResponse(wrapped = testUser)) as Api.Details<T>

但随后我收到一条警告,通知我“此转换永远不会成功” - 运行我的测试,它确实按预期工作。

我的问题是 - 为什么在没有强制转换的情况下这不起作用?我应该使用什么来代替?

最佳答案

方差注释可能会帮助您,只需将以下函数中的泛型参数 T 更改为 out Obj(在接口(interface)和实现类中):

fun <T: Obj> getDetails(type: KClass<T>, uuid: String): Details<out Obj>

关于generics - 从泛型函数返回特定实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37727319/

相关文章:

Java泛型类型转换之谜

android - GLES20.glUniform4fv和fragshader

android - Kotlin 数据类 |添加我自己的变量而不是 JSON 键

android - 如何使用导航组件向变化的 fragment 添加动画?

C# Language : generics, open/closed, bound/unbound, constructed

arrays - 为什么数组不符合 Equatable,而它的项在 Swift 中是 Equatable 的?

generics - 实现 BaseDao 的多个 Daos 的存储库类委托(delegate) - 可能吗?

c# - 我可以使用代码契约来解决无法使用通用构造函数约束的问题吗?

Android Kotlin - 无法解析 Firebase

java - Android 为什么应用程序可以在真实设备上的 Android Studio 上运行,但上传到商店后出现错误