Given an ev: Manifest[T]
I can get a Class[T]
using ev.erasure.asInstanceOf[Class[T]]
. It's a shame that ev.erasure
alone returns a static type of Class[_]
.
Can I get a Class[T]
from a manifest without casting? If not is there a reason why the blessed Scala creators have gone for a raw return type in the erasure
method?
I understand this may have a negligible impact on most code but I've run into this issue in an arguably non-idiomatic piece of Scala code and am curious more than anything else.
The reason for returning the erased type is that
Manifest
is almost always used in generic code where you don't actually have the type in hand. This forces you to explicitly declare your intentions instead of mistakenly assuming that it actually checks that the type is the one you want.You can of course use the enrich my library pattern to add your own method that preserves types:
No, you have to do the cast yourself — and it should be so. This cast is potentially unsafe, depending on what you want to do with the returned
Class
instance. Imagine I want to roll in my own version of a cast:This is dangerous — as indicated by the unchecked
asInstanceOf
. Why? Because this code runs fine with such nonsense, for instance:There, a
List[Int]
typed as aList[String]
. And this compiles and runs fine, but you'll probably get aClassCastException
later in your code at an unexpected line. That's why you cannot directly get aClass[T]
from aManifest[T]
— because it is unsafe.Scala's typesystem isn't expressive enough to give the correct type for
erasure
. The correct type would be similar to the one forgetClass()
:In this case, I think the correct type would be
Class[|X|]
(becauseManifest[T]
is invariant in its type parameter). This is different toObject.getClass()
, because in that case the static type and runtime type could be different:Here, the runtime type of
c
would beClass<Integer>
, notClass<Number>
.