約反射簡單的問題在斯卡拉:枚舉子類的字段斯卡拉
- 我如何寫一個方法
fields
返回一個特定類型的所有領域,即使在子類? - 即使是正確的做法嗎?如果不是,你會怎麼做?
例子:
class Top { def fields = ... }
class A extends Top {
val f1 = Field(...)
val f2 = Field(...)
}
(new A).fields // List(f1, f2)
約反射簡單的問題在斯卡拉:枚舉子類的字段斯卡拉
fields
返回一個特定類型的所有領域,即使在子類?例子:
class Top { def fields = ... }
class A extends Top {
val f1 = Field(...)
val f2 = Field(...)
}
(new A).fields // List(f1, f2)
所以,在我的試驗和錯誤,我發現真正的運行時類型反射是困難的,因爲Scala的在編譯時嵌入類型信息的絕招,當你請求隱式TypeTag。我發現的是,如果你想反思一個對象的類型,該對象的類型必須在編譯時可用。 (這可能反映了我的知識限制,而不是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)
注意,我必須明確地命名自己的類型時,我伸出基地,所以在編譯時,適當TypeTag可以嵌入(作爲隱入我的構造函數)。我只是不知道這個方法。
vals以TermSymbols列表的形式返回此處。我不確定你想要什麼;如果您只想要String val名稱,請將「.map(_.name.toString.trim)」添加到stringVals函數的末尾。 (我發現修剪的重要性在實踐中很重要,但是我敢打賭,隨着反射庫的敲定和演變將變得多餘。)
祝你好運!
很好的答案,+1的實際例子!我首先想到你可以使用'typeOf [this.type]'來引用子類的類型,但它似乎總是指'Base' ... –
看到這裏的一些例子:http://stackoverflow.com/questions/1898932/case-classes-vs-enumerations-in-scala – sschaef
嗯,我接受的答案實際上回答我的問題更好,但感謝您的鏈接;) –