Lets pretend we have an interface which defines the storage of data in some database by serializing them into json.
interface StorageApi {
suspend fun store(key: String, value: Any)
// inline suspend fun <reified T: Any> get(key: String): T // reification is not possible in interfaces since we can't inline them
suspend fun <T: Any> get(key: String, kClass: KClass<T>): T // so I have to stick with some other way, like reflection.
}
And then we have an implementation of the method:
override suspend fun <T : Any> get(key: String, kClass: KClass<T>): T {
val value = // some query to database
return Klaxon().parse<T>(value) // obviously error by compiler since T goes through type-erasure
}
Here I cannot use T as it would go through Type-erasure at runtime. I have reflection but don't know how to use it in this purpose. The Klaxon.parse() function does not accept KClass for getting types.
Is there any way to bypass these or make some utility to use reflection in this purpose, or any other possible workarounds?
I am fairly sure that if you break the inlined reification chain at any point, and start working with classes (
KClassinstances, that is), there is unfortunately no going back, exactly for the reasons you've described.What's even worse is that a
KClasscan't hold type parameters, so if your reified parameter was aList<Something>for example, then you've lost information there already - another reason for no going back to reification.The sad conclusion is that you probably have to deal with
KClassin a case like this.