sen
sen

Reputation: 198

How to type cast Any dynamically in scala?

I want to convert "Any" object into an object of runtime type. Based on the class name (string) at the runtime, how do I convert an ANY object to actual object?

I tried using converting class name into class object using Class.forName

val clazz = Class.forName("my.package.Animal")
val any: Any = Animal(1, "simba")
any.asInstanceOf[clazz] // Compilation Error // Looking for a solution

Upvotes: 3

Views: 1670

Answers (1)

Dmytro Mitin
Dmytro Mitin

Reputation: 51648

Try to use

  • compiler toolbox

    package my.package
    
    import scala.tools.reflect.ToolBox
    import scala.reflect.runtime.universe._
    
    case class Animal(id: Int, name: String)
    
    object App {    
      val any: Any = Animal(1, "simba")
      val className = "my.package.Animal"
    
      val mirror = runtimeMirror(getClass.getClassLoader)
      val tb = mirror.mkToolBox()
      tb.eval(tb.parse(
        s"""
          import my.package.App._
          val animal = any.asInstanceOf[$className]
          println(animal.id)
          println(animal.name)
        """))
    }
    

libraryDependencies += scalaOrganization.value % "scala-reflect" % scalaVersion.value

libraryDependencies += scalaOrganization.value % "scala-compiler" % scalaVersion.value

  • or Scala reflection

    import scala.reflect.runtime.universe._
    
    val mirror = runtimeMirror(getClass.getClassLoader)
    val classSymbol = mirror.staticClass(className)
    val typ = classSymbol.toType
    val idMethodSymbol = typ.decl(TermName("id")).asMethod
    val nameMethodSymbol = typ.decl(TermName("name")).asMethod
    val instanceMirror = mirror.reflect(any)
    val idMethodMirror = instanceMirror.reflectMethod(idMethodSymbol)
    val nameMethodMirror = instanceMirror.reflectMethod(nameMethodSymbol)
    println(idMethodMirror())
    println(nameMethodMirror())
    

libraryDependencies += scalaOrganization.value % "scala-reflect" % scalaVersion.value

  • or Java reflection

    val clazz = Class.forName(className)
    val idMethod = clazz.getMethod("id")
    val nameMethod = clazz.getMethod("name")
    println(idMethod.invoke(any))
    println(nameMethod.invoke(any))
    

Upvotes: 1

Related Questions