I have a map of type Map[_, Any]
, and I want to extract the values in their native format (without resorting to .asInstanceOf[_]
).
Something like this...
val m: Map[String, Any] = Map("i" -> 1, "s" -> "test")
val i: Option[Int] = m.get("i")
val s: Option[String] = m.get("s")
Obviously that fails.
I don't like this approach, but I was thinking I could do something like this... but even this still comes out as Any
instead of Int
or String
.
trait MyType[A] {
def value: A
}
implicit class MyInt(i: Int) extends MyType[Int] { def value: Int = i }
implicit class MyString(s: String) extends MyType[String] { def value: String = s }
val m: Map[String, MyType[_]] = Map("i" -> 1, "s" -> "test")
val i: Option[Int] = m.get("i").map(_.value)
val s: Option[String] = m.get("s").map(_.value)
Then I thought maybe some wrapper around the Map
...
case class MyMap(m: Map[String, Any]) {
def get[A](k: String)(implicit ev: Option[Any] => Option[A]): Option[A] = m.get(k)
}
But that STILL comes out as Any
. I just can't figure out how to convert Any => native.
So my questions are...
- Why does this fail?
- What are better way(s) to get the values out in their native format? Simplest and/or no external dependencies would be ideal... but I'm honestly open to anything (though caveat I'm still on scala 2.11 for now).
Thanks!
You cannot guess the runtime type for the reasons that have already been explained in the comments - this information is not there, once it's
Any
, all type information is lost, there is nothing you can do about it.So, you'll have to provide the expected type yourself. How about an
.as[T]
helper method?This will print
Brief explanation:
As
wrapper "pimps" all the objects, and attaches an.as
method to everything.unapply
does the checking, the casting, and the wrapping in anOption
.It will not work for generic types like
List[Int]
vs.List[String]
etc, because this information is simply not available at runtime.EDIT: Thanks @MarioGalic for greatly simplifying the solution.