Enumerate the fields of a subclass in Scala

北城以北 提交于 2020-01-04 06:03:56

问题


Simple question about reflection in Scala :

  • How can I write a method fields that returns all the fields of a certain type, even in subclasses?
  • Is that even the right way to do it? How would you do it if it is not?

Example :

class Top { def fields = ... }
class A extends Top {
  val f1 = Field(...)
  val f2 = Field(...)
}

(new A).fields // List(f1, f2)

回答1:


So, in my trials and errors, I've found genuine run-time type reflection to be difficult, because of Scala's trick of embedding type information at compile time when you ask for an implicit TypeTag. What I've found is that, if you want to reflect on the Type of an object, that object's type must have been available at compile time. (That may reflect a limitation of my knowledge rather than a limitation of Scala reflection, but I have tried and so far failed to reflect on runtime types that cannot be captured at compile time.)

So, here is closest to what you want that I know how to do:

scala> import scala.reflect.runtime.universe._;
import scala.reflect.runtime.universe._

scala> class Base[T <: Base[T] : TypeTag] {
     | def stringVals = typeOf[T].members.filter( _.isTerm ).map( _.asTerm).filter( _.isVal ).filter( _.typeSignature <:< typeOf[String] )
     | }
defined class Base

scala> class Derived extends Base[Derived] {
     | val f1 = "Bye";
     | val f2 = 27;
     | val f3 = "Sad.";
     | }
defined class Derived

scala> (new Derived).stringVals
res0: Iterable[reflect.runtime.universe.TermSymbol] = List(value f3, value f1)

Note that I had to explicitly name my own type when I extended Base, so that at compile time, the appropriate TypeTag could be embedded (as an implicit into my constructor). I just don't know a way around that.

The vals are returned here in the form of a List of TermSymbols. I'm not sure what you wanted; if you just wanted String val names, add ".map( _.name.toString.trim )" to the end of the stringVals function. (I've found the call to trim to be important in practice, but I bet as the reflection library finalizes and evolves it will become superfluous.)

Good luck!



来源:https://stackoverflow.com/questions/15784320/enumerate-the-fields-of-a-subclass-in-scala

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!