Why does Scala reflection work inside an object bu

2019-09-08 12:54发布

问题:

This script uses reflection to find the type signature of a constructor. It contains the same code inside an object and at the top level:

// Scala 2.11.1
case class Dirigible(cubicFeet: Int)

object Object {
  val u = scala.reflect.runtime.universe
  val ctor = u.weakTypeOf[Dirigible].decl(u.termNames.CONSTRUCTOR).typeSignature
  def run() {
    println(ctor)
  }
}

Object.run()

val u = scala.reflect.runtime.universe
val ctor = u.weakTypeOf[Dirigible].decl(u.termNames.CONSTRUCTOR).typeSignature
println(ctor)

Here is the output:

(cubicFeet: Int)$anon.this.Dirigible
<notype>

Why does the top-level code fail while the code inside Object works?

The same failure occurs if I put the println inside a top-level def and call it from the top level.

The top-level code works if I run the file in the REPL via scala -i refltest.scala. That's to be expected, since the REPL puts everything into an object. What I don't understand is, why does code's being inside an object affect the results of reflection?

回答1:

The script runner wraps your code in a local anonymous class; your code is run as part of the initializer.

I don't know why that breaks reflection, but it's a duplicate of this question from a couple of years ago. That was edited to say the problem was fixed, but I don't see it working.

As a workaround, wrap your code in a block:

locally {
val u = scala.reflect.runtime.universe
val ctor = u.weakTypeOf[Dirigible].decl(u.termNames.CONSTRUCTOR).typeSignature
println(ctor)
}

Maybe it has to do with init order and how the local class is compiled.