繁体   English   中英

当类型嵌套时,通过密封超级特征的反射来恢复单例实例

[英]Recovering a singleton instance via reflection from sealed super trait, when type is nested

当它是嵌套类型时,我无法通过其密封的超特性通过反射来恢复单例实例:

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

(我从取了身体这个主旨尤金Burmako。)


如果您更改为

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

有用...

这还不是一个答案,但也许可以解决,以防万一。

第一次对我有用,但对我却没有,因为科学不就是重现结果吗?:

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

初始化了一些东西,但是我还没有看到。 我注意到我这样做了:

scala> cm reflect Foo
res13: reflect.runtime.universe.InstanceMirror = instance mirror for Foo$@3a854a76

好吧,这是一个文本记录,它在您进行所有操作时都调用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

也许我们已经大到可以记住此错误了。

为了完整性而不是封闭性:

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)
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM