pygumby
pygumby

Reputation: 6790

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?

Upvotes: 0

Views: 150

Answers (1)

Michael Zajac
Michael Zajac

Reputation: 55569

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.

Upvotes: 2

Related Questions