Basically, I want to have a Map indexed by type objects. In this case, I'm trying to use Class as the "type type".
the following code:
class SuperClass {}
val typemap = new HashMap[Class[_ <: SuperClass], SuperClass]
def insertItem1[T <: SuperC开发者_Go百科lass] (item : T) = typemap += classOf[T] -> item
def insertItem2[T <: SuperClass] (item : T) = typemap += item.getClass -> item
does not compile, because (1) classOf[T] is apparently invalid:
error: class type required but T found
and (2) item.getClass is of the wrong type:
Type mismatch, expected: Class[_ <: SuperClass], actual: Class[_]
I see two ways to accomplish this:
either drop the type requirement and use Class[_] only or use Manifest instead of Class (not sure how to do that yet, any examples are welcome)But more generally, why is classOf[T] invalid, and how do I obtain a class object for a parametrized type?
update: I found out that I can use item.getClass.asInstanceOf[Class[T]]
to get to the class object. For one, this is ugly. For two, it doesn't help much, because later in the code i have functions such as this one:
def isPresent[T <: SuperClass] = typemap contains classOf[T]
Obviously, I could use the asInstanceOf method in insertItem
and pass the class as a parameter to isPresent
. Is there a better way?
You can use manifests to achieve this:
class TypeMap extends HashMap[Class[_], Any] {
def putThing[T](t: T)(implicit m: Manifest[T]) = put(m.erasure, t)
}
val map = new TypeMap
map.putThing(4)
map.get(classOf[Int]) // returns Option[Any] = Some(4)
You are losing the types through erasure, so you need to add the implicit argument to the putThing which contains the name of the class, using a Manifest.
The problem is once again that generics aren't available at run time. The compiler does the task of figuring out what T
is, but it can't because it is only know at run time.
You could use a manifest to obtain that information: What is a Manifest in Scala and when do you need it?.
精彩评论