Scala reflection to access all public fields at runtime

前端 未结 3 1722
栀梦
栀梦 2021-01-04 11:23

Given the following class hierarchy:

class A {
  val x = 3
  val y = 4
}

class B extends A {
  val z = 5
}

And say I have an instance of B

3条回答
  •  梦谈多话
    2021-01-04 11:58

    You can you TypeTag to get an access:

    scala> import scala.reflect.runtime.universe._
    import scala.reflect.runtime.universe._
    
    scala> class A {
         |   val x = 3
         |   val y = 4
         | }
    defined class A
    
    scala> class B extends A {
         |   val z = 5
         | }
    defined class B
    
    scala> typeOf[B]
    res0: reflect.runtime.universe.Type = B
    

    Now you have two options: members which shows all members (even inherited ones) and declarations (only defined in the current class), e.g:

    scala> res0.declarations
    res2: reflect.runtime.universe.MemberScope = SynchronizedOps(constructor B, value z, value z)
    

    If you want to work with this field you need reflect them through InstanceMirror:

    scala> val b = new B
    b: B = B@6ebe10dd
    
    scala> val currentMirror = runtimeMirror(getClass.getClassLoader)
    .....
    
    scala> val bMir = currentMirror.reflect(b)
    bMir: reflect.runtime.universe.InstanceMirror = instance mirror for B@6ebe10dd
    

    Now you just need to get a Symbol you need, e.g you want to get a value of z varible:

    scala> val zt = typeOf[B].declaration("z": TermName).asMethod
    zt: reflect.runtime.universe.MethodSymbol = value z
    
    scala> bMir.reflectField(zt).get
    res20: Any = 5
    

提交回复
热议问题