使用新的ScalareflectionAPI获取伴随对象实例
使用Scala的新reflectionAPI,是否可以获得对类的伴随对象的引用? 我正在这样思考:
trait Base { def companion: MetaBase = someReflectionMagic(this).asInstanceOf[MetaBase] } trait MetaBase { // stuff } // --- class Foo extends Base object Foo extends MetaBase assert(new Foo.companion == Foo)
戴夫! 感谢您对新的思考感兴趣。 早期的采用者已经在很大程度上推动了反思和macros的开发过程,我很高兴能够成为我们令人惊叹的社区的一部分。
在回答你的问题之前,我想先从一个免责声明开始。 在2.10.0-M4中,我们刚刚奠定了ScalareflectionAPI的基础。 新闻报道仍然很热,所以文档非常稀缺,API也不是很方便。 它工作,但它需要testing和反馈。 当然,搞乱预发布的API是很麻烦的,但我总是在这里帮忙。
到目前为止,我们有一个将来将成为反思SIP的草案: https : //docs.google.com/document/d/1Z1VhhNPplbUpaZPIYdc0_EUv5RiGQ2X4oqp0i-vz1qw/edit#heading=h.pqwdkl1226tc 。 您可以马上阅读,也可以先浏览下面的答案。
trait Base { def companion: MetaBase = { // runtime reflection is typically done // by importing things from scala.reflect.runtime package import scala.reflect.runtime._ // the new Scala reflection API is mirror based // mirrors constitute a hierarchy of objects // that closely follows the hierarchy of the things they reflect // for example, for a class you'll have a ClassMirror // for a method you'll have a MethodMirror and so on // why go the extra mile? // because this provides more flexibility than traditional approaches // you can read more about mirror-based designs here: // https://dl.dropbox.com/u/10497693/Library/Computer%20Science/Metaprogramming/Reflection/mirrors.pdf // https://dl.dropbox.com/u/10497693/Library/Computer%20Science/Metaprogramming/Reflection/reflecting-scala.pdf // bottom line is that to do anything you will need a mirror // for example, in your case, you need a ClassMirror // remember I said that mirrors provide more flexibility? // for one, this means that mirror-based reflection facilities // might have multiple implementations // in a paper linked above, Gilad Bracha muses over a runtime // that loads things remotely over the network // in our case we might have different mirrors for JVM and CLR // well, anyways // the canonical (and the only one now) implementation of the mirror API // is Java-based reflection that uses out of the box classloaders // here's its root: https://github.com/scalamacros/kepler/blob/9f71e9f114c10b52350c6c4ec757159f06e55daa/src/reflect/scala/reflect/api/Mirrors.scala#L178 // yeah, right, I've just linked a source file from trunk // we'll have Scaladocs for that soon, but for now take a look // this file is interfaces-only and is heavy on comments // to start with Java-based reflection implementation you need a classloader // let's grab one and instantiate the root mirror // btw, the same effect could be achieved by writing // `scala.reflect.runtime.currentMirror` val rootMirror = universe.runtimeMirror(getClass.getClassLoader) // now when we've finally entered the reflective world // we can get the stuff done // first we obtain a ClassSymbol that corresponds to the current instance // (ClassSymbols are to Scala the same as Classes are to Java) var classSymbol = rootMirror.classSymbol(getClass) // having a Scala reflection entity // we can obtain its reflection using the rootMirror val classMirror = rootMirror.reflectClass(classSymbol) // now we just traverse the conceptual hierarchy of mirrors // that closely follows the hierarchy of Scala reflection concepts // for example, a ClassMirror has a companion ModuleMirror and vice versa val moduleMirror = classMirror.companion.get // finally, we've arrived at our destination moduleMirror.instance.asInstanceOf[MetaBase] } } trait MetaBase { // stuff } // --- class Foo extends Base object Foo extends MetaBase object Test extends App { assert(new Foo().companion == Foo) }
更新。 请参阅Daniel Sobral的优秀post: http : //dcsobral.blogspot.ch/2012/07/json-serialization-with-reflection-in.html 。
我没有看到尤金的最后一个评论,并提出了这一点。 它适用于斯卡拉2.10。
trait ReflectionSugars{ import scala.reflect.runtime.{universe => ru} private lazy val universeMirror = ru.runtimeMirror(getClass.getClassLoader) def companionOf[T](implicit tt: ru.TypeTag[T]) = { val companionMirror = universeMirror.reflectModule(ru.typeOf[T].typeSymbol.companionSymbol.asModule) companionMirror.instance } } trait X extends ReflectionSugars{ def companion = companionOf[X] }
https://gist.github.com/piotrga/5928581
我希望这有帮助!