Hello,
As far as I could find, this question has not been posted before. If it has, I would be happy to view that forum post.
Edit: I just found Can generic parameters be reified at class level?, no idea why it did not pop up in the first place…
I have a use case where there is a collection of items, with some generic type. I need to filter the items in the collection based on their generic type, and then invoke some specific function on the items using data that only compiles if the types I just checked (filtered on) are correct.
In code:
class Item<T> {
val clazz : Class<T>
// other properties
fun operation (t: T) { /* ... */ }
}
val value: Long = ...
val specificClass: Class<Long> = ...
val items : List<Item<*>> = ....
items.filter { it.clazz == specificClass }
.forEach { it.operation(value) }
// ^^^^^^^^^^^^ Here I would need to cast each item
// to Item<Long>, even though I just checked that
// it.clazz == Long::class
I would like to have that code like:
val items : List<Item<*>> = ....
items.filterInstanceOf<Item<Long>>()
.forEach { it.operation(value) } // <-- Smart cast to Item<Long>
At the moment this is not possible, because classes cannot have reified generic parameters (only inline functions can have them). Would a language extension be possible where classes with some of their generic parameters annotated as reifed
be available at runtime?
A small example of the code it could generate automatically:
class Item<reified T>
// ... would be equivalent to ...
class Item<T> {
val genericClassArgument0: Class<T>
}
(just like componentN()
for data classes).
Then, we would need to fill the parameter for every constructor call. That could work in the following way (just like an inline function):
class Item<reified T>(val value: Long)
val item = Item<UUID>(Random.nextLong())
// ... this would actually call ...
// Item(UUID::class, Random.nextLong())
// and bytecode would just contain the constructor with the Class<*>, Long arguments
I hope this makes the idea clear. Thanks in advance for any reactions.