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]) = {
...
}