When trying to get object field by its string name, the value returned, not by correct scala type. As:
import scala.language.reflectiveCalls
import scala.language.implicitConversions
case class Intity(flag: Boolean, id: Int, name: String)
val inty = Intity(false, 123, "blue")
implicit def reflect(r: AnyRef) = new {
def get(n:String) = {
val c = r.getClass.getDeclaredField(n)
c.setAccessible(true); c}
def getVal(n: String) = get(n).get(r)
def getType (n:String) = get(n).getType
}
then when using this
inty.getType("flag") // res0: Class[_] = boolean --not Boolean
inty.getVal("id") // res1: Object = 123 --Object not Int
Any efficient way of doing the above implementation?
If we want to access Private Field and method using Reflection we just need to call setAccessible(true) on the field or method object which you want to access. Class. getDeclaredField(String fieldName) or Class. getDeclaredFields() can be used to get private fields.
We can use newInstance() method on the constructor object to instantiate a new instance of the class. Since we use reflection when we don't have the classes information at compile time, we can assign it to Object and then further use reflection to access it's fields and invoke it's methods.
Reflection is a feature in the Java programming language. It allows an executing Java program to examine or "introspect" upon itself, and manipulate internal properties of the program. For example, it's possible for a Java class to obtain the names of all its members and display them.
Not sure, how one can return different types from a single function. But you can infer the correct type of any Class attribute using scala reflect api(s).
import scala.reflect.runtime.{universe => ru}
implicit class ForAnyInstance[T: ru.TypeTag](i: T)(implicit c: scala.reflect.ClassTag[T]) {
/* a mirror sets a scope of the entities on which we have reflective access */
val mirror = ru.runtimeMirror(getClass.getClassLoader)
/* here we get an instance mirror to reflect on an instance */
val im = ru.runtimeMirror(i.getClass.getClassLoader)
def fieldInfo(name: String) = {
ru.typeOf[T].members.filter(!_.isMethod).filter(_.name.decoded.trim.equals(name)).foreach(s => {
val fieldValue = im.reflect(i).reflectField(s.asTerm).get
/* typeSignature contains runtime type information about a Symbol */
s.typeSignature match {
case x if x =:= ru.typeOf[String] => /* do something */
case x if x =:= ru.typeOf[Int] => /* do something */
case x if x =:= ru.typeOf[Boolean] => /* do something */
}
})
}
}
And then invoke it as:
case class Entity(flag: Boolean, id: Int, name: String)
val e = Entity(false, 123, "blue")
e.fieldInfo("flag")
e.fieldInfo("id")
You can do something similar at compile time with shapeless.
scala> import shapeless._
import shapeless._
scala> val inty = Intity(false, 123, "blue")
inty: Intity = Intity(false,123,blue)
scala> val intyGen = LabelledGeneric[Intity].to(inty)
intyGen: shapeless.::[Boolean with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("flag")],Boolean],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("id")],Int],shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.HNil]]] = false :: 123 :: blue :: HNil
scala> import shapeless.record._
import shapeless.record._
scala> intyGen.get('flag)
res10: Boolean = false
scala> intyGen.get(Symbol("id"))
res11: Int = 123
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With