3

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
Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
sen
  • 198
  • 2
  • 9
  • May I ask, why do you need this? I hope there are better alternatives that a runtime cast. – Luis Miguel Mejía Suárez Jul 19 '19 at 21:39
  • thanks @luis-miguel-mejía-suárez. I stored POJO objects in a file as byte arrays. And I have a mapping of files to objects. When I am trying to read POJOs from file, I have to convert them to right objects. – sen Jul 19 '19 at 21:44
  • 3
    But why do you need to cast? Are you going to call methods on those objects? How will you know at compile time which methods are available if the cast is dynamic? – Jasper-M Jul 19 '19 at 21:47
  • I have to call bunch of setter functions using these objects. Guess I can do a pattern match and set them – sen Jul 19 '19 at 21:54
  • 4
    @sen I know there could be reasons that would not allow you. But, I would suggest you to change those **POJOS** to **Case Classes** and use a serializer, deserializer that is capable of returning correct types like [**Circe**](https://github.com/circe/circe) would do for JSONs. - Now, assuming you can not change the code, can you share a real use case of your code? Like, how do you read them, how do you call the setters and how would you want to cast them. – Luis Miguel Mejía Suárez Jul 19 '19 at 21:56

1 Answers1

1

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))
    
Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66