Home > Back-end >  scala function to operate on any case class
scala function to operate on any case class

Time:02-20

I've been trying ot create a function that does some inflection on any case class but can't figure out how to pull it off on non concrete generic types, what am I doing wrong?

Please note I can't change the original case classes passed to this function

        def caseClassToArray[A](something: A) = {
          classOf[A]
          .getDeclaredFields
          .map { f: Field =>
          f.setAccessible(true)
          val res = (f.getName, f.get(something))
          f.setAccessible(false)
          res
        }
    }

CodePudding user response:

If you are looking for a way to do reflection, the answer of @Silvio is good.

However to achieve the same output, you should rely on standard methods provided by the library and not use reflection:

def caseClassToArray[A <: Product](instance: A): Array[(String, Any)] = {
  a.productElementNames.zipWith(a.productIterator)
}

See https://www.scala-lang.org/api/current/scala/Product.html (all case classes inherit from Product).

CodePudding user response:

Scala, like Java, erases generic types at runtime. So if you want to do something at runtime with the generic type A, you need to take an implicit ClassTag argument.

import scala.reflect._
import java.lang.reflect._

def caseClassToArray[A](something: A)(implicit cls: ClassTag[A]) = {
  cls.runtimeClass // <-- Instead of classOf[A]
    .getDeclaredFields
    .map { f: Field =>
      f.setAccessible(true)
      val res = (f.getName, f.get(something))
      f.setAccessible(false)
      res
    }
}

In Scala 3, that looks like

def caseClassToArray[A](something: A)(using cls: ClassTag[A]) = {
  ...
}
  • Related