Reputation: 1315
I have written a generic function to get a value from a HashMap[String, AnyVal]. This method returns a value from the name but also has a functionality to make sure it is of a specific type:
class Context {
private var variables = HashMap[String, Any] ()
def getVariable (name: String):Any = variables(name)
def setVariable (name: String, value: Any) = variables += ((name, value))
def getVariableOfType[T <: AnyVal] (name:String):T ={
val v = variables(name)
v match {
case T => v.asInstanceOf[T]
case _ => null.asInstanceOf[T]
}
}
}
The function getVariableOfType[T <: AnyVal] will not compile because it says "Cannot resolve symbol T" at the line case T => v.asInstanceOf[T]
Upvotes: 2
Views: 599
Reputation: 14224
Simply having case x: T => v.asInstanceOf[T]
will match any type because of erasure. To really do the type checking you have to make a ClassTag
available for T
: [T <: AnyVal : ClassTag]
.
Here is a working definition of getVariableOfType
:
import scala.reflect.ClassTag
def getVariableOfType[T <: AnyVal : ClassTag] (name:String):T ={
val v = variables(name)
v match {
case x: T => x
case _ => null.asInstanceOf[T]
}
}
The downside is that ClassTag
doesn't completely remove the issue of erasure. So requesting for example a Seq[Int]
, will actually match on every type of sequence (Seq[Double]
, Seq[String]
, etc.). In your example T
is a subtype of AnyVal
, so this won't be an issue.
Upvotes: 6