Subclassing HashMap in Scala, Working on Type Erasure

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.

+4
source share
1 answer

Please note: while

 case s: Some[T] 

It does not work, because a parameter of type Some is erased, this is different:

 case s @ Some(_: T) 

In this case, it does not work, because T is the type parameter itself. Although this does not affect your case (no, there is no other way than the manifest), consider the following:

 case s: Some[Int] // erased case s @ Some(_: Int) // not erased 
+2
source

Source: https://habr.com/ru/post/1369036/


All Articles