2013-06-09 1 views
2

У меня возникли проблемы оправляются одноэлементный экземпляр через отражение от запечатанной супер признака, когда вложенный тип:Восстановления одноэлементного экземпляра через отражение от запечатанной супер признака, когда тип вложен

import reflect.runtime.universe._ 
import reflect.runtime.{currentMirror => cm} 

object Foo { 
    case object Bar extends Foo 
} 
sealed trait Foo 

def getModule(tpe: Type): Any = { 
    val classSymbol = tpe.typeSymbol.asClass 
    val compSymbol = classSymbol.companionSymbol // gives <none> ! 
    val moduleSymbol = compSymbol.asModule 
    val moduleMirror = cm.reflectModule(moduleSymbol) 
    moduleMirror.instance 
} 

val subs  = typeOf[Foo].typeSymbol.asClass.knownDirectSubclasses 
val tpeOther = subs.last.asType.toType 

val res = getModule(tpeOther) 
println(res) 

Вызов чтобы companionSymbol не дает "нет", и asModule терпит неудачу с

scala.ScalaReflectionException: <none> is not a module 

(я принял тело от this Gist Евгений Burmako.)


Если вы смените

sealed trait Foo 
case object Bar extends Foo // not nested in object Foo 

это работает ...

ответ

4

Это не ответ еще, но, возможно, обходные, в случае, если это помогает любому.

Он работал для меня в первый раз, но не во второй раз, потому что это не наука все о воспроизводя результаты ?:

scala> res22.head 
res24: reflect.runtime.universe.Symbol = object Bar 

scala> .asClass 
res25: reflect.runtime.universe.ClassSymbol = object Bar 

scala> .isModule 
isModule  isModuleClass 

scala> .isModuleClass 
res26: Boolean = true 

scala> res25.companionSymbol 
res27: reflect.runtime.universe.Symbol = object Bar 

scala> .isModule 
res28: Boolean = true 

И позвольте мне просто проверить:

scala> cm reflectModule res27.asModule 
res30: reflect.runtime.universe.ModuleMirror = module mirror for Foo.Bar (bound to null) 

scala> .instance 
res31: Any = Bar 

Копирование каждая команда точно работает, поэтому не состояние гонки:

scala> typeOf[Foo].typeSymbol.asClass.knownDirectSubclasses.head 
res29: reflect.runtime.universe.Symbol = object Bar 

scala> .asClass 
res30: reflect.runtime.universe.ClassSymbol = object Bar 

scala> .companionSymbol 
res31: reflect.runtime.universe.Symbol = object Bar 

scala> .asModule 
res32: reflect.runtime.universe.ModuleSymbol = object Bar 

Что-то началось, bu Я еще не вижу, что. Я заметил, что я сделал это:

scala> cm reflect Foo 
res13: reflect.runtime.universe.InstanceMirror = instance mirror for [email protected] 

Ну, вот стенограмма вызова typeSig на все, как вы идете:

scala> import reflect.runtime.universe._ 
import reflect.runtime.universe._ 

scala> import reflect.runtime.{currentMirror => cm} 
import reflect.runtime.{currentMirror=>cm} 

scala> :pa 
// Entering paste mode (ctrl-D to finish) 

sealed trait Foo 
object Foo { 
    case object Bar extends Foo 
} 

// Exiting paste mode, now interpreting. 

defined trait Foo 
defined object Foo 

scala> typeOf[Foo].typeSymbol 
res0: reflect.runtime.universe.Symbol = trait Foo 

scala> res0.typeSignature 
res1: reflect.runtime.universe.Type = scala.AnyRef 

scala> res0.asClass 
res2: reflect.runtime.universe.ClassSymbol = trait Foo 

scala> .companionSymbol 
res3: reflect.runtime.universe.Symbol = object Foo 

scala> .typeSignature 
res4: reflect.runtime.universe.Type = Foo.type 

scala> res2.knownDirectSubclasses.head.asClass 
res5: reflect.runtime.universe.ClassSymbol = object Bar 

Это одна не является необходимым в данном случае:

scala> res5.typeSignature 
res6: reflect.runtime.universe.Type = 
scala.AnyRef 
     with Foo 
     with scala.Product 
     with scala.Serializable { 
    def <init>(): Foo.Bar.type 
    override def productPrefix: java.lang.String 
    def productArity: scala.Int 
    def productElement(x$1: scala.Int): scala.Any 
    override def productIterator: Iterator[scala.Any] 
    def canEqual(x$1: scala.Any): scala.Boolean 
    override def hashCode(): scala.Int 
    override def toString(): java.lang.String 
    private def readResolve(): java.lang.Object 
} 

scala> res5.companionSymbol 
res7: reflect.runtime.universe.Symbol = object Bar 

scala> res7.isModule 
res8: Boolean = true 

scala> cm reflectModule res7.asModule 
res9: reflect.runtime.universe.ModuleMirror = module mirror for Foo.Bar (bound to null) 

scala> .instance 
res10: Any = Bar 

Возможно, мы достаточно взрослые, чтобы помнить this bug.

Для полноты, но не для закрытия:

object Driller extends App { 
    def getModule(sym: Symbol): Any = { 
    val classSymbol = sym.asClass 
    val compSymbol = classSymbol.companionSymbol // gives <none> ! 
    val moduleSymbol = compSymbol.asModule 
    val moduleMirror = cm.reflectModule(moduleSymbol) 
    moduleMirror.instance 
    } 
    val foo = typeOf[Foo].typeSymbol.asClass 
    foo.typeSignature 
    foo.companionSymbol.typeSignature 
    val bar = foo.knownDirectSubclasses.head.asClass 
    val res = getModule(bar) 
    println(res) 
} 
+0

Спасибо за внимание. Это действительно похоже на проблему с инициализацией. Во всяком случае, работа вокруг достаточно хороша для моего дела. Важнейшим вызовом является 'foo.companionSymbol.typeSignature' (' foo.typeSignature' не требуется). –

+0

@ 0__ Да, это определенно усилие зеленой отметки. Вы не спрашивали, в чем исправить ошибку отражения? –

+0

Здесь вы идете 9 :) –