vendredi 25 mars 2016

Get particular public fields via reflection (for all parent classes)

How to get all fields with particular type from some object instance including all its parent-classes?

For example, there are these classes:

trait Target {
    val message: String
    def action: Unit = println("hello", message)
}

class ConcreteTarget(val message: String) extends Target

trait BaseSet {
  val s = ""
  val t1 = new ConcreteTarget("A")
  val t2 = new ConcreteTarget("B")
  val a = 123
}

class ExtendedSet extends BaseSet {
  val t3 = new ConcreteTarget("C")
  val f = "111"
}

I've tried write method for getting all Target fields:

import scala.reflect.runtime.universe._
import scala.reflect.runtime.{universe => ru}

def find(instance: Any): List[Target] = {
    val m = ru.runtimeMirror(instance.getClass.getClassLoader)
    val i = m.reflect(instance)

    i.symbol.typeSignature.decls.flatMap {
      case f: TermSymbol if !f.isMethod => i.reflectField(f).get match {
        case d: Target => Some(d)
        case _ => None
      }
      case _ => None
    }.toList
}

This method works fine for BaseSet:

find(new BaseSet{}) foreach (f => f.action)
//> (hello,A)
//> (hello,B)

But finds only public fields from ExtendedSet and don't find parents fields:

find(new ExtendedSet) foreach (f => f.action)
//> (hello,C)

What is wrong?





Aucun commentaire:

Enregistrer un commentaire