2012-06-13 6 views
27

スカラの新しいリフレクションAPIを使用すると、クラスのコンパニオンオブジェクトへの参照を取得できますか?私はこれらのラインに沿って何かを考えています:新しいスカラリフレクションAPIを使用してコンパニオンオブジェクトインスタンスを取得

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) 
+0

私はあなたがこのようなもので逃げることができると思うhttp://stackoverflow.com/questions/1913092/getting-object-instance-by-string-name-in-scala – Noah

+3

私は何かを望んでいた新しいリフレクションAPIを使用して、 – leedm777

答えて

37

デイブ!新しいリサーチに興味をお持ちいただきありがとうございます。早期採用者は、リフレクションやマクロの開発プロセスを大幅に進めてきました。私は、驚くべきコミュニティの一部であることに非常に満足しています。

質問に答える前に、私は免責事項から始めたいと思います。 2.10.0-M4では、ScalaリフレクションAPIの基礎を築きました。それはまだ報道の日では暑いので、ドキュメントは非常に不足しており、APIは便宜をもって完全にはぎとられていません。それは動作しますが、テストとフィードバックが必要です。もちろん、プレリリース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) 
} 

更新。ダニエル・ソブラルの優れた投稿:http://dcsobral.blogspot.ch/2012/07/json-serialization-with-reflection-in.htmlもご覧ください。

+0

[この質問](http://stackoverflow.com/q/10893712/53013)も参照してください。 –

+0

このコードを更新してscala 2.10.0の最終版で動作させるにはどうすればよいですか? –

+3

https://gist.github.com/xeno-by/4985929 –

5

私はユージーンの最後のコメントを見ていないとこれを思い付いた。スカラ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

関連する問題