Scala cast to a variable type
casting, scala
Solution
Because of type erasure, it's impossible to actually implement `value.{as/is}InstanceOf[T]` where `T` is a type parameter. Scala's designers decided it should still compile, but `value.asInstanceOf[T]` is actually a no-op (just like the equivalent `(T) value` in Java), while `value.isInstanceOf[T]` always returns `true` (in Java, `value instanceOf T` is a compiler error). (Since it never does what you want, I'd strongly like to see a warning instead, at least for `isInstanceOf`.)
But Scala allows to do what you want using `ClassTag`:
import scala.reflect.ClassTag
def fct[T](value: Any, default: T)(implicit tag: ClassTag[T]): T = {
val result = (tag match {
case ClassTag.Int => value.asInstanceOf[Int]
... same for other primitives
case _ => tag.runtimeClass.cast(value)
}).asInstanceOf[T]
println(result, result.getClass.getName, tag.runtimeClass.isInstance(result))
result
}
(You still need `asInstanceOf[T]` because `tag.runtimeClass` usually returns the same class `T` represents but not always, so its static return type has to be `Class[_]` and `cast` returns `Any`).
However, pattern-matching `: T` handles presence of a `ClassTag` automatically and already handles boxing, so
def fct[T](value: Any, default: T)(implicit tag: ClassTag[T]): T = value match {
case result: T => result
case _ => default // or whatever you want to do if value is not a T
}
is the better way to do this.
Problem
I have the following code to cast value to the type of default: ``` def fct[T](value: Any, default: T): T = { val result = value.asInstanceOf[T] println(result, result.getClass.getName, result.isInstanceOf[T]) result } val res = fct("foo", 42) ``` Which result is: ``` (foo,java.lang.String,true) java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer at scala.runtime.BoxesRunTime.unboxToInt(Test.sc2.tmp) at #worksheet#.res$lzycompute(Test.sc2.tmp:7) at #worksheet#.res(Test.sc2.tmp:7) at #worksheet#.#worksheet#(Test.sc2.tmp:7) ``` Question is: why the println is displayed? The cast should fail. I tried to try / catch the 3 lines but no exception are raised during the function call.