scala反射:getDeclaringTrait?

Itt*_*ayD 7 reflection scala

当我研究一个新的库时,我有时会发现很难找到一个方法的实现.

在Java中,Metho#getDeclaringClass提供声明给定方法的类.因此,通过迭代Class#getMethods,我可以找到每个方法,声明它的类.

在Scala中,traits被转换为Java接口,并且扩展trait的类将通过将它们转发到静态定义这些方法的伴随类来实现trait的方法.这意味着,Method#getDeclaringClass将返回类,而不是特征:

scala> trait A { def foo = {println("hi")}}
defined trait A

scala> class B extends A
defined class B

scala> classOf[B].getMethods.find(_.getName() == "foo").get.getDeclaringClass
res3: java.lang.Class[_] = class B
Run Code Online (Sandbox Code Playgroud)

解决这个问题的最佳方法是什么?意思是,给定一个类,我如何得到一个List [(Method,Class)],其中每个元组是一个方法,并且它被声明为trait/class?

Tho*_*ung 6

在Scala 2.8中,您可以使用ScalaSigParser来解析scala特定的字节代码信息.

这将比scala特征,类和方法的字节码序列化格式更稳定.

import tools.scalap.scalax.rules.scalasig._
import scala.runtime._

val scalaSig = ScalaSigParser.parse(classOf[RichDouble]).get
val richDoubleSymbol = scalaSig.topLevelClasses.head
val methods = richDoubleSymbol.children filter ( _ match {
    case m : MethodSymbol => true
    case _ => false
})

methods foreach println
richDoubleSymbol.isTrait
ScalaSigParser.parse(classOf[Ordered[Any]]).get.topLevelClasses.head.isTrait
Run Code Online (Sandbox Code Playgroud)

打印:

scala> methods foreach println
MethodSymbol(x, owner=0, flags=20080004, info=23 ,None)
MethodSymbol(<init>, owner=0, flags=200, info=33 ,None)
[...]
MethodSymbol(isPosInfinity, owner=0, flags=200, info=117 ,None)
MethodSymbol(isNegInfinity, owner=0, flags=200, info=117 ,None)

scala> richDoubleSymbol.isTrait
res1: Boolean = false

scala> ScalaSigParser.parse(classOf[Ordered[Any]]).get.topLevelClasses.head.isTrait
res2: Boolean = true
Run Code Online (Sandbox Code Playgroud)

我想按照这条道路,你可以为Scala构建一个反射API.