我想计算Scala类的包名。
下面的代码有效,但似乎有点冗长
def packagename(cls:ru.ClassSymbol):String = {
def innerPackageName(cls:JavaUniverse#Symbol):List[JavaUniverse#Name] = {
if(cls.owner != null && cls.owner.isPackage ) {
List(cls.name) ::: innerPackageName(cls.owner)
}
else {
List(cls.name)
}
}
val owner: JavaUniverse#Symbol = cls.owner
innerPackageName(owner).filterNot{_.toString == "<root>"}.reverse.mkString(":")
}
有更好的方法吗?
答案 0 :(得分:7)
遍历所有者链直到您命中包(或者更准确地说是包类)的概念是正确的,但是您发布的代码具有轻微的风格问题。首先,有Symbol.fullName
为你连接字符串。其次,公开使用反射API所需的魔术名称通常会在API中的某处显示。
以下是我要执行的操作(如果您使用的是Scala 2.10.x,请将newTermName
更改为TermName
):
00:08 ~/Projects/Master/sandbox (master)$ cat Test.scala
import scala.reflect.runtime.universe._
import scala.reflect.runtime.{currentMirror => cm}
object Test extends App {
def packageName(sym: Symbol) = {
def enclosingPackage(sym: Symbol): Symbol = {
if (sym == NoSymbol) NoSymbol
else if (sym.isPackage) sym
else enclosingPackage(sym.owner)
}
val pkg = enclosingPackage(sym)
if (pkg == cm.EmptyPackageClass) ""
else pkg.fullName
}
println(packageName(typeOf[Test.type].member(TermName("packageName"))))
println(packageName(cm.staticPackage("scala")))
println(packageName(cm.staticClass("scala.collection.immutable.List")))
}
00:08 ~/Projects/Master/sandbox (master)$ sr
scala
scala.collection.immutable