Mention generics to anyone who knows much about them and they’ll usually have an opinion on type reification and erasure. For the uninitiated, erasure is where a List of Strings (or a List parameterised by the String type) “forgets” that it has been parameterised by the String type once it has been compiled – ie. the type parameter is erased. Reification is the opposite, the type is remembered, or reified.
Different platforms have different strategies for their generics implementations. For example C++ templates compile completely different bytes for vector<string> to vector<int>. Java on the other hand uses exactly the same byte-code for all implementations – underneath the covers it is just List<Object> – relying on the compiler to make sure the client code does the right thing (it also inserts the correct casts for you).
There are many opinions on the relative merits of either approach, and erasure has much to recommend it, but erasure has a very specific draw-back: it doesn’t tell you at runtime what its actual type is.
Not knowing the runtime type is usually not a problem, but very occasionally you need it. For instance, you sometimes want to construct an Array of your specific type T, and for that you need the specific Class<T> to do so. You cannot at runtime reconstruct the T without it*.
Another example is a library that may need a representation of the type at runtime (usually via a Class instance, no longer a type but a type token) so it can do something with it, like look up a specific implementation from it.
An example is in our page-objects library (a front-end testing library built upon WebDriver). To get a specific Page object you give it a Class<P extends Page> and it returns an instance of that page class:
and use it:
This last is quite handy, and very common in our tests but it does have some unnecessary duplication and boilerplate. Fortunately we can eliminate that in Scala.
Scala has the ability to automagically produce values via implicit resolution. It also (in 2.8/2.9) has a feature known as Class Manifests. Using a Manifest we create the following helper for the above:
this says, given some type parameter P that is a subtype of Page and has-a Manifest[P], call app.visit and pass the class instance that we implicitly summon (using manifest[P], a shorthand for implicitly[Manifest[P]]). Lastly (and unfortunately) we don’t in the type know the erased class’s type, but by construction we know it is correct so we cast using asInstanceOf[Class[P]].
We can now use this:
and we no longer need to pass the Class instance directly, we simply pass the type parameter!
This would be of small value if it didn’t have a bunch of transitive benefits. You can build trees of related implicit dependencies (ie. they compose). You can use the pattern of having the related class (the Manifest in this case) provide type-specific behaviour, ie. the type-class pattern.
So, using implicits to summon type tags, Scala can use erased generics and still get all the benefits of reification.
* arrays are not erased, although they are covariant and mutable which is the devil’s work.