您可以使用 Java 的 Proxy 创建一个 trait 实例,该实例从对 trait 的 ...$ setter $... 方法的所有调用中收集值。这是一个骇人听闻的例子:
object Reflection {
def traitInits(clazz : Class[_]) : Map[String, Object] = {
var cl = clazz.getClassLoader
if (cl == null) {
cl = ClassLoader.getSystemClassLoader
}
var init : Option[java.lang.reflect.Method] = None
try {
for (m <- cl.loadClass(clazz.getName + "$class").getMethods if init.isEmpty)
if (m.getName == "$init$")
init = Some(m)
} catch {
case e : Exception =>
}
if (init.isEmpty) return Map()
var encodedToDecodedSetterNameMap = Map[String, String]()
for (m <- clazz.getDeclaredMethods()) {
val setterPrefix = clazz.getName.replace('.', '$') + "$_setter_$"
val encoded = m.getName
if (encoded.startsWith(setterPrefix)) {
val decoded = encoded.substring(setterPrefix.length, encoded.length - 4)
encodedToDecodedSetterNameMap += (encoded -> decoded)
}
}
var result = Map[String, Object]()
import java.lang.reflect.InvocationHandler
import java.lang.reflect.Proxy
init.get.invoke(null, Proxy.newProxyInstance(cl, Array[Class[_]](clazz),
new InvocationHandler {
def invoke(proxy : Object,
method : java.lang.reflect.Method,
args : Array[Object]) = {
encodedToDecodedSetterNameMap.get(method.getName) match {
case Some(decodedName) => result += (decodedName -> args(0))
case _ =>
}
null
}
}))
result
} //> traitInits: (clazz: Class[_])Map[String,Object]
trait A {
val x : Int = 3
val y : String = "y"
}
traitInits(classOf[A]) //> res0: Map[String,Object] = Map(x -> 3, y -> y)
}