为什么scala将本地定义的类与外部作用域中的类区别对待?

时间:2016-04-18 21:08:32

标签: scala

编译器在下面的每个类声明中看到的不同之处是导致typeOf的行为不同。 (即类声明的属性是什么导致它失败)。

import org.junit.Test
import scala.reflect.runtime.universe._


case class Person1(name: String)
class ReflectTest {

  case class Person2(name: String)

  @Test
  def constructorTest(): Unit = {

    case class Person3(name: String)

    typeOf[Person1]  // Yep
    typeOf[Person2]  // No problem
    typeOf[Person3]  // No typetag information available :(
  }
}

1 个答案:

答案 0 :(得分:1)

这是一种免费类型。你不能用前缀来引用它。

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

scala> class C { class D }
defined class C

scala> val c = new C
c: C = C@29626d54

scala> val x = { final class X ; weakTypeTag[X] }
x: reflect.runtime.universe.WeakTypeTag[_ <: AnyRef] = WeakTypeTag[X]

scala> val t = typeTag[C]
t: reflect.runtime.universe.TypeTag[C] = TypeTag[C]

scala> val w = typeTag[c.D]
w: reflect.runtime.universe.TypeTag[c.D] = TypeTag[c.D]

scala> val v = typeTag[C#D]
v: reflect.runtime.universe.TypeTag[C#D] = TypeTag[C#D]

scala> (t.tpe.typeSymbol, t.tpe.typeSymbol.isStatic)
res1: (reflect.runtime.universe.Symbol, Boolean) = (class C,true)

scala> (x.tpe.typeSymbol, x.tpe.typeSymbol.isStatic)
res2: (reflect.runtime.universe.Symbol, Boolean) = (free type X,false)

scala> (w.tpe.typeSymbol, w.tpe.typeSymbol.isStatic)
res3: (reflect.runtime.universe.Symbol, Boolean) = (class D,false)

scala> (v.tpe.typeSymbol, v.tpe.typeSymbol.isStatic)
res4: (reflect.runtime.universe.Symbol, Boolean) = (class D,false)

scala> reflect.runtime.universe.internal.asFreeType(x.tpe.typeSymbol)
res5: reflect.runtime.universe.FreeTypeSymbol = free type X

本地课程无法做到的其他事情,如mentioned in the spec

scala> val x = { private class X ; weakTypeTag[X] }
<console>:1: error: illegal start of statement (no modifiers allowed here)
val x = { private class X ; weakTypeTag[X] }
          ^

scala> import c.D
import c.D

我看起来更多,但现在已经很晚了,我的REPL破了...

scala> val y = { final class X { class Y } ; val x = new X ; import x.Y ; weakTypeTag[Y] } 
warning: there was one feature warning; re-run with -feature for details
java.lang.AssertionError: assertion failed: x.type
    at scala.reflect.internal.tpe.TypeMaps$adaptToNewRunMap$.adaptToNewRun(TypeMaps.scala:1106)
    at scala.reflect.internal.tpe.TypeMaps$adaptToNewRunMap$.apply(TypeMaps.scala:1150)
    at scala.reflect.internal.tpe.TypeMaps$adaptToNewRunMap$.apply(TypeMaps.scala:1079)
    at scala.reflect.internal.tpe.TypeMaps$adaptToNewRunMap$.apply(TypeMaps.scala:1148)
    at scala.reflect.internal.tpe.TypeMaps$TypeMap.mapOver(TypeMaps.scala:162)
    at scala.reflect.internal.tpe.TypeMaps$adaptToNewRunMap$.apply(TypeMaps.scala:1197)
    at scala.reflect.internal.tpe.TypeMaps$adaptToNewRunMap$.apply(TypeMaps.scala:1171)
    at scala.reflect.internal.Symbols$Symbol.adaptInfos(Symbols.scala:1629)
    at scala.reflect.internal.Symbols$Symbol.rawInfo(Symbols.scala:1581)
    at scala.tools.nsc.typechecker.Typers$Typer.isStale(Typers.scala:504)
    at scala.tools.nsc.typechecker.Typers$Typer.reallyExists(Typers.scala:496)
    at scala.tools.nsc.typechecker.Typers$Typer.typedSelectInternal$1(Typers.scala:4712)
    at scala.tools.nsc.typechecker.Typers$Typer.typedSelect$1(Typers.scala:4676)