带有TypeTags和单例类型的Scala反射

时间:2013-12-18 20:28:07

标签: scala reflection types

我刚刚开始尝试使用Scala 2.10中引入的反射API,并期望下面的代码评估为真五次(REPL)。

不幸的是,只有第一个和最后一个表达式确实存在。有人可以解释为什么会这样吗?从编译器的角度来看,似乎所有这些类型的比较都没问题,或者我错了吗?

有没有办法让这个(至少有一个.type比较)工作?

import scala.reflect.runtime.universe._

class Test[A:TypeTag](val a:A) {
  val value:this.type=this
  def t1:TypeTag[Test[A]]=typeTag[Test[A]]
  def t2:TypeTag[this.type]=typeTag[this.type]
  def t3:TypeTag[_<:Test[A]]=typeTag[this.type]
}

val a:Test[String]=new Test("a")

a.t1.tpe<:<typeOf[Test[String]] //works as expected
a.t2.tpe<:<typeOf[Test[String]] //FAILS
a.t3.tpe<:<typeOf[Test[String]] //FAILS
a.t2.tpe<:<typeOf[a.type] //FAILS
typeOf[a.type]<:<typeOf[a.type] //this works again

使用Scala REPL 2.10.3和2.11.0-M7进行测试。

此致

梅西

2 个答案:

答案 0 :(得分:2)

显然,你的班级不知道它的类型参数。你的t2方法不起作用可能是一个错误。

规范说

  

单例类型p .type符合路径p的类型。

这里的情况仍然如此,因为Test只是Test[A]。但由于A的标签可用,您认为它会使用它。

scala> typeTag[a.type].tpe
res8: reflect.runtime.universe.Type = a.type

scala> typeTag[a.type].tpe.widen
res9: reflect.runtime.universe.Type = Test[String]

scala> typeTag[a.type].tpe.widen <:< typeOf[Test[String]]
res10: Boolean = true

scala> typeTag[a.type].tpe <:< typeOf[Test[String]]
res11: Boolean = true

scala> a.t2.tpe
res12: reflect.runtime.universe.Type = Test.this.type

scala> a.t2.tpe.widen
res13: reflect.runtime.universe.Type = Test[A]

答案 1 :(得分:1)

这里要记住的基本事实是单例类型与对象(具体实例)无关。相反,它们与标识符相关联。

这意味着单个对象可以有多个单例类型,具体取决于它所分配的标识符。例如:

class C {
  val self = this
  val thistpe = typeOf[this.type]
  type T1 = this.type
  type T2 = self.type
}

val c1 = new C
val c2 = c1
val c3: c1.type = c1

val tpe1 = typeOf[c1.type]
val tpe2 = typeOf[c2.type]
val tpe3 = typeOf[c3.type]
val tpe4 = typeOf[c1.T1]
val tpe5 = typeOf[c1.T2]
val tpe6 = c1.thistpe

在上面的代码段中,tpe1tpe3tpe4将被识别为相同类型,但其他类型不会。

在你的情况下,你可以尝试这样的事情:

class C {
  def thisTpe(implicit tag: TypeTag[this.type]) = tag.tpe
}

val c = new C
c.thisTpe =:= typeOf[c.type] // yields true