scalarookie scalarookie - 1 month ago 13
Scala Question

Performing an explicit cast based on `Class` instance

Assume there is a class

X
. At some point in my code, I get an
o
of type
Object
and I want to explicitly cast it to
X
. Normally, I would do
val x: X = o.asInstanceOf[X]
. However,
X
is not in scope, all I have is
X
's instance of
Class
, like so:


  1. I pass
    classOf[X]
    to my function as an argument called
    classOfX
    .

  2. Within my function, I would like to do
    val x: X = o.asInstanceOf[classOfX]
    .



Is there a way to do this in Scala?

m-z m-z
Answer

Only kind of. java.lang.Class has a cast method that lets you cast a Class[A] to an A. You could write a method like this:

def cast[A](o: Any, clazz: Class[A]): A = clazz.cast(o)

scala> cast("abc", classOf[String])
res10: String = abc

This will "work" for most classes, but not for Scala boxed primitives:

scala> cast(1, classOf[Int])
java.lang.ClassCastException: Cannot cast java.lang.Integer to int

And of course, casting only works modulo type erasure, so this will not immediately throw an exception:

scala> val a = List("a").getClass
a: Class[_ <: List[String]] = class scala.collection.immutable.$colon$colon

scala> cast(List(1), a)
res16: List[String] = List(1)

On the upside, it will also work with classes obtained at run time using getClass, like above.

The downside is that you should be avoiding casting at all costs, because of how error prone it will make the code. It throws type safety out the window. Rarely should anyone find themselves in a situation where they have an object where they don't know what it is, but can somehow tell the compiler what it is using classOf. It is likely that using some form of generics could eliminate a casting problem, but it is impossible to tell without more code.

Comments