Search code examples
scalacollectionstype-systems

how to make a collection of type objects in Scala


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 <: SuperClass] (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?


Solution

  • 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.