我刚刚开始尝试使用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进行测试。
此致
梅西
答案 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
在上面的代码段中,tpe1
,tpe3
和tpe4
将被识别为相同类型,但其他类型不会。
在你的情况下,你可以尝试这样的事情:
class C {
def thisTpe(implicit tag: TypeTag[this.type]) = tag.tpe
}
val c = new C
c.thisTpe =:= typeOf[c.type] // yields true