Let's say that for some reason I want a common HashMap to contain all types of objects. I also want to push any unsightly checks like t20 into the data structure. For this purpose, it would be convenient to use a method such as getAs[T <: Any](key: String): Option[T] .
class State extends HashMap[String, Any] { override def +[T >: Any](elem: (String, T)): State = super.+(elem) override def -(key: String): State = super.-(key) def getAs[T](key: String): Option[T] = { super.get(key) match { case s: Some[T] => s case _ => None } } } object State extends HashMap[String, Any] { override def empty: State = super.empty }
I also have the following implicit conversion defined in the package object:
implicit def fromHashMap(m: HashMap[String, Any]): State = m.asInstanceOf[State]
When I compile the above code, I get the following type erase warning:
State.scala:10: warning: non variable type-argument T in type pattern Some[T] is unchecked since it is eliminated by erasure case s: Some[T] => s ^
This is unfortunate, since the whole purpose of this statement is to check the type!
In this case, do I have an option other than resorting to the experimental manifest functions? Moreover, is there a better basic approach to achieve this?
Edit:
I worked with Manifests. This article in Stackoverflow helped me a lot. However, I'm still wondering if there is a cleaner way that anyone can recommend.
Dual Editing:
Here is the current version of this. The manifestos solved my immediate problems. However, the main change I made was to make the State class a wrapper for the Map. However, I lost the benefits of inheritance (i.e. now I have to explicitly expose each method of the map. I need a la keySet below.
class State( map: HashMap[String, (Manifest[_], Any)] = scala.collection.immutable.HashMap.empty[String, (Manifest[_], Any)] ) extends java.io.Serializable { def +[T <: Any](elem: (String, T))(implicit m: Manifest[T]): State = State(map.+((elem._1, (m, elem._2)))) def -(key: String): State = State(map.-(key)) def keySet = map.keySet def getAs[T](key: String)(implicit m : Manifest[T]): Option[T] = { map.get(key) match { case Some((om: Manifest[_], o: Any)) => if (om <:< m) Some(o.asInstanceOf[T]) else None case _ => None } } } object State { def apply() = new State() def apply(map: HashMap[String, (Manifest[_], Any)]) = new State(map) def empty = State() }
Thanks to everyone who has looked at this so far.
Update for Scala 2.10:
See the current implementation of State with ClassTag and friends here on GitHub . I plan to update it to use TypeTag once TypeCreator serializable.