枚举Scala中子类的字段



关于Scala反射的简单问题:

  • 我怎么能写一个方法fields返回某一类型的所有字段,甚至在子类?
  • 这是正确的做法吗?如果不是,你会怎么做?

的例子:

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

因此,在我的试验和错误中,我发现真正的运行时类型反射是困难的,因为当您要求隐式TypeTag时,Scala会在编译时嵌入类型信息。我发现,如果你想反映一个对象的类型,该对象的类型必须在编译时可用。(这可能反映了我的知识的限制,而不是Scala反射的限制,但我已经尝试过,到目前为止,没有反映出不能在编译时捕获的运行时类型。)

那么,这里是最接近你想要的,我知道怎么做的:

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)

注意,在扩展Base时必须显式地命名自己的类型,以便在编译时可以嵌入适当的TypeTag(作为隐式嵌入到构造函数中)。我只是不知道如何解决这个问题。

这里的值以TermSymbols列表的形式返回。我不知道你想要什么;如果您只想要字符串val名称,请添加"。map(_.name.toString.trim)"到stringVals函数的末尾。(我发现调用trim在实践中很重要,但我打赌随着反射库的最终完成和发展,它将变得多余。)

祝你好运!

相关内容

  • 没有找到相关文章