What about reified generics?


#1

I've read that Kotlin should have reified generics (like C#), but this information comes from older blog posts. The documentation about generics doesn't say anything about reification (and nothing about the type erasure). What is the state of reified generics in Kotlin?


#2

It does not seem to be implemented yet or ever.

But reified generics is not supported by any JVM, and Kotlin cannot do anything about that.

What it can do is emulating reified generics by carrying a manifest around that contains
generics information.
Scala, Gosu and Ceylon does that.

There is price you have to pay for that: increasing complexity. It can hurt performance badly,
and it can hurt interoperability with Java.

I don’t think it is justified to pay that price. I think we should just accept that Java does
erasure due to the need to remain backward compatible. Kotlin does and should do the same.

Optional reification might make sense, but I don’t think I would use it that often or ever.


#3

Before the answer about reified generics, could you please describe what you would be using them for?


#4

I had several issues with type erasure in the last years, but I try to remember ...

You cannot overload methods with the same signature after erasure:

// Java - doesn’t compile!

public void process(List<String> list) { … }
public void process(List<Something> list) { … }

You cannot use types to distinguish event listeners with type erasure, see Why use an annotation to mark handler methods, rather than requiring the listener to implement an interface?

You cannot implement a generic repository and access the concrete type at runtime (without tricks).


#5

Kotlin can distinguish these overloads of course, so you can use "platformName" annotation to resolve conflicts when compiled down to JVM bytecode:

platformName(“averageInt”)
fun Iterable<Int>.average() : Int = …

platformName(“averageLong”)
fun Iterable<Long>.average() : Int = …


#6

You cannot use types to distinguish event listeners with type erasure, see Why use an annotation to mark handler methods, rather than requiring the listener to implement an interface?

I'm not sure this is really a problem. Now we have

class EventBusChangeRecorder {
    @Subscribe void recordSmallCustomerChange(SmallChangeEvent e) {...}
    @Subscribe void recordBigCustomerChange(BigChangeEvent e) {...}
}

If there was no erasure, we could write

class EventBusChangeRecorder implements
        EventBusListener<SmallChangeEvent>,
        EventBusListener<BigChangeEvent> {
    @Override void listen(SmallChangeEvent e) {...}
    @Override void listen(BigChangeEvent e) {...}
}

but is this really better? I don’t know. In any case it’d open a huge can of worms. Imagine something like

boolean b = doesTheClassImplement(EventBusChangeRecorder.class,
      EventBusListener<?>.typeLiteral)

Should b be true or false, or maybe 2? It doesn’t implement EventBusListener<?>, but it does implement a subtype of it, actually twice.


#7

Another interesting point about reified generics: Why There Is Interface Pollution in Java 8