![](/img/trans.png)
[英]How to inherit generic types in implementations without having generic interfaces in Kotlin?
[英]How to write generic functions in Kotlin interfaces's implementations
我正在尝试实现一个像这样的通用 HttpClient:
interface HttpClient {
fun <T: Any> get(url: String): T?
}
由 class 实现,如下所示:
class HttpClientImpl @Inject constructor(...) : HttpClient {
override fun <T : Any> get(url: String): T? = execute(url)
private inline fun <reified T: Any> execute(url: String): T? {
val request = Request.Builder().url(url).get().build()
client.newCall(request).execute().use {
return it.body?.parseBodySuccess()
}
}
private inline fun <reified T: Any> ResponseBody?.parseBody(): T? {
val type = objectMapper.typeFactory.constructType(T::class.java)
return this?.let { objectMapper.readValue(it.string(), type) }
}
}
现在,我希望能够以这种方式调用这样的 GET 方法:
data class MyEntity(...)
class MyService @Inject constructor(private val client: HttpClient) {
fun performGet(url: String): MyEntity? = client.get<MyEntity>(url)
}
然而,这是不允许的,编译器会抛出一个引用代码行的错误
override fun <T : Any> get(endpoint: String): T? = execute(endpoint)
标记为:不能使用“T”作为具体化类型参数。 请改用 class。
我一直在尝试将该行重写为
override inline fun <reified T : Any> get(endpoint: String): T? = execute(endpoint)
然而,尽管必须将其他两个内联函数设置为“非私有”,编译器仍然无法编译,因为在最后一种编写覆盖 function 的方法中,它说:
由具有具体化类型参数的 function 覆盖
我怎样才能实现这样的通用 function?
我最终做了这样的事情:
interface HttpClient {
fun <T: Any> get(url: String, type: Class<T>): T?
}
实现为:
class HttpClientImpl @Inject constructor(...) : HttpClient {
override fun <T : Any> get(url: String, type: Class<T>): T? = execute(url, type)
private fun <T: Any> execute(url: String, type: Class<T>): T? {
val request = Request.Builder().url(url).get().build()
client.newCall(request).execute().use {
return it.body?.parseBody(type)
}
}
private fun <T: Any> ResponseBody?.parseBody(type: Class<T>): T? {
val dataType = objectMapper.typeFactory.constructType(type)
return this?.let { objectMapper.readValue(it.string(), dataType) }
}
}
我可以这样调用:
data class MyEntity(...)
class MyService @Inject constructor(private val client: HttpClient) {
fun performGet(url: String): MyEntity? = client.get(url, MyEntity::class.java)
}
我宁愿将类型直接作为实际类型传递,例如
client.get<MyEntity>(url)
而不是将 Class 作为参数传递,但是,只是现在它可以工作......
如果有人可以建议更好的方法,请告诉我。
更新
正如 Pawel 所建议的,我已经为 HttpClient 接口创建了一个额外的内联扩展 function
inline fun <reified T:Any> HttpClient.get (url: String) = get(url, T::class.java)
我现在可以按照我想要的方式拨打 function。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.