Reputation: 1086
I'm trying implement some particular GSON TypeAdapter in Kotlin language for my android project.
The issue I'm facing is compile error with inability to infer type: Type inference failed: 'T' cannot capture 'in (T..T?'. Type parameter has an upper bound 'Enum<T>' that cannot be satisfied capturing 'in' projection
The code is following:
class SmartEnumTypeAdapterFactory(fallbackKey: String) : TypeAdapterFactory {
private val fallbackKey = fallbackKey.toLowerCase(Locale.US)
override fun <T : Any> create(gson: Gson?, type: TypeToken<T>): TypeAdapter<T>? {
val rawType = type.rawType
return if (!rawType.isEnum) null else SmartEnumTypeAdapter(rawType)
}
class SmartEnumTypeAdapter<T : Enum<T>>(classOfT: Class<T>) : TypeAdapter<T>() {
override fun write(out: JsonWriter?, value: T) {
TODO("not implemented")
}
override fun read(`in`: JsonReader?): T {
TODO("not implemented")
}
}
}
The reason I want to have classOfT: Class<T>
as parameter for TypeAdapter is out of context of this problem.
Upvotes: 5
Views: 2693
Reputation: 1268
This is not possible because the method you are overwriting (TypeFactory.create
) has no upper bound (which translates to <T : Any>
in Kotlin). In your create
method, T
is not
guaranteed to be a Enum<T>
(so, it's not possible to pass it as argument to your adapter).
What you can do is simply remove the upper bound in your adapter class and keep it private to make sure only your factory can create instances of it (and the factory already validates if the type is an enum).
class SmartEnumTypeAdapterFactory(fallbackKey: String) : TypeAdapterFactory {
private val fallbackKey = fallbackKey.toLowerCase(Locale.US)
override fun <T> create(gson: Gson?, type: TypeToken<T>): TypeAdapter<T>? {
val rawType = type.rawType
return if (!rawType.isEnum) null else SmartEnumTypeAdapter(rawType)
}
private class SmartEnumTypeAdapter<T>(classOfT: Class<in T>) : TypeAdapter<T>() {
override fun write(out: JsonWriter?, value: T) {
TODO("not implemented")
}
override fun read(`in`: JsonReader?): T {
TODO("not implemented")
}
}
}
(classOfT
is a Class<in T>
because TypeToken.rawType()
returns a Class<? super T>
)
Upvotes: 2