我正在尝试用Kotlin编写一个改装转换器。但是,在尝试返回转换器时,我卡住了:
class JSONRPCConverterFactory private constructor(private val gson : Gson): Converter.Factory() {
companion object {
private val MEDIA_TYPE = MediaType.get("application/json")
fun create(gson: Gson) = JSONRPCConverterFactory(gson)
}
inner class JSONRPCRequestBodyConverter<T : JSONRPCRequest<*>>(private val gson: Gson) : Converter<T, RequestBody> {
override fun convert(value: T): RequestBody? {
val jsonString = gson.toJson(value, object:TypeToken<T>(){}.type)
return RequestBody.create(MEDIA_TYPE, jsonString)
}
}
inner class JSONRPCResponseBodyConverter<T>(private val gson: Gson) : Converter<ResponseBody, T> {
override fun convert(value: ResponseBody): T? {
return gson.fromJson(value.string(), object:TypeToken<T>(){}.type)
}
}
override fun responseBodyConverter(type: Type, annotations: Array<Annotation>, retrofit: Retrofit): Converter<ResponseBody, *>? {
if (!hasJSONRPCAnnotation(annotations)) return null
return JSONRPCResponseBodyConverter(gson)
}
override fun requestBodyConverter(type: Type, parameterAnnotations: Array<Annotation>, methodAnnotations: Array<Annotation>, retrofit: Retrofit): Converter<*, RequestBody>? {
if (!hasJSONRPCAnnotation(methodAnnotations)) return null
return JSONRPCRequestBodyConverter(gson)
}
private fun hasJSONRPCAnnotation(annotations: Array<Annotation>) : Boolean {
for (annotation in annotations) {
if (annotation is JSONRPC) return true
}
return false
}
}
错误出现在这两行:
return JSONRPCResponseBodyConverter(gson)
和
return JSONRPCRequestBodyConverter(gson)
类型推断失败:没有足够的信息来推断
中的参数T构造函数JSONRPCRequestBodyConverter>(gson: Gson)
请明确指定。
在Java中,可能仅返回new JSONRPCResponseBodyConverter<>(gson)
。但是,在kotlin中,该类型是必需的,因此仅添加<>
也会失败。
使用Kotlin-lang:Kotlin Serialization Converter查看此转换器,我发现它使用几乎相同的类结构,并且仅返回了一个没有菱形的新转换器,并且可以正常工作。
我想念什么?
答案 0 :(得分:1)
问题在于JSONRPCResponseBodyConverter
和JSONRPCRequestBodyConverter
都需要一个类型参数T
,并且编译器无法在调用站点上推断出这种类型。您看到的示例可能具有某种推断T类型的方式,例如T的参数或它要赋值的类型。
class A<T>(t: T? = null)
val a1 : A<Int> = A() //this will work, it can infer the type from the asigment
val a2 = A(2) //this will work, it can infer the type from the parameter
val a3 = A() //this won't work, the compiler has no way of knowing the type of T