在 Scala 中枚举子类的字段 [英] Enumerate the fields of a subclass in Scala

查看:33
本文介绍了在 Scala 中枚举子类的字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于 Scala 反射的简单问题:

Simple question about reflection in Scala :

  • 如何编写一个方法 fields 来返回特定类型的所有字段,即使是在子类中?
  • 这是正确的做法吗?如果不是,你会怎么做?
  • 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?

示例:

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

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

推荐答案

所以,在我的试验和错误中,我发现真正的运行时类型反射很困难,因为 Scala 在编译时嵌入类型信息的技巧当您要求隐式 TypeTag 时.我发现,如果您想反映对象的类型,则该对象的类型必须在编译时可用.(这可能反映了我知识的局限性,而不是 Scala 反射的局限性,但我已经尝试过,但迄今为止未能反映在编译时无法捕获的运行时类型.)

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)

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

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.

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

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.)

祝你好运!

这篇关于在 Scala 中枚举子类的字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆