方差和ClassTags
或之间有什么联系TypeTags
?
我有两种类型,T1
和T2
,用作类型参数。
case class T1()
case class T2()
我有一个带有不变类型参数和一个子类的抽象类,如果我想检查类型参数的类型,则只有在模式中没有类型检查时才起作用,只是在后卫中。如果存在类型测试,它将始终选择第一种情况。
类型检查是必需的,因为在我的真实代码中,我想为每种类型调用不同的函数。有单独的功能In[T1]
和In[T2]
。
abstract class In[T]
case class VIn[T]() extends In[T]
def test1[T:ClassTag](v:In[T]) = v match {
case x : VIn[T1@unchecked] if classTag[T] == classTag[T1] => "T1"
case y : VIn[T2@unchecked] if classTag[T] == classTag[T2] => "T2"
}
test1(VIn[T1]()) //T1
test1(VIn[T2]()) //T1 !!!
def test2[T:ClassTag](v:In[T]) = v match {
case x if classTag[T] == classTag[T1] => "T1"
case y if classTag[T] == classTag[T2] => "T2"
}
test2(VIn[T1]()) //T1
test2(VIn[T2]()) //T2
List
在处理许多示例中使用的类型时,我意识到,如果将type参数更改为协变量,则可以在两种测试中使用。
abstract class Co[+T]
case class VCo[T]() extends Co[T]
def test1[T:ClassTag](v:Co[T]) = v match {
case x : VCo[T1@unchecked] if classTag[T] == classTag[T1] => "T1"
case y : VCo[T2@unchecked] if classTag[T] == classTag[T2] => "T2"
}
test1(VCo[T1]()) // T1
test1(VCo[T2]()) // T2
def test2[T:ClassTag](v:Co[T]) = v match {
case x if classTag[T] == classTag[T1] => "T1"
case y if classTag[T] == classTag[T2] => "T2"
}
test2(VCo[T1]()) // T1
test2(VCo[T2]()) // T2
为什么invarinat类型的第一个测试失败?没有编译器警告或运行时错误,它只是选择第一种情况,但是防护显然是错误的,如中所示test2
。
我绝对认为这是一个编译器错误。
def test1[T:ClassTag](v:In[T]) = {
val t1 = classTag[T] == classTag[T1]
val t2 = classTag[T] == classTag[T2]
println(v match {
case x : VIn[T1@unchecked] if t1 => "T1"
case y : VIn[T2@unchecked] if t2 => "T2"
})
v match {
case x:In[T1] if classTag[T] == classTag[T1] => "T1"
case y: In[T2] if classTag[T] == classTag[T2] => "T2"
}}
打印时-Xprint:typer
显示(evidence
):
def test1[T](v: In[T])(implicit evidence$1: scala.reflect.ClassTag[T]): String = {
....
val t1: Boolean = scala.reflect.`package`.classTag[T](evidence$1).==
(scala.reflect.`package`.classTag[T1]((ClassTag.apply[T1](classOf[T1]): scala.reflect.ClassTag[T1])))
val t2: Boolean = scala.reflect.`package`.classTag[T](evidence$1).==
(scala.reflect.`package`.classTag[T2]((ClassTag.apply[T2](classOf[T2]): scala.reflect.ClassTag[T2]))) //classTag[T] == classTag[T2]
if
模式匹配的语句为:
scala.reflect.`package`.classTag[T](evidence$1).==(scala.reflect.`package`.classTag[T1](evidence$1))
scala.reflect.`package`.classTag[T](evidence$1).==(scala.reflect.`package`.classTag[T2](evidence$1))
编译器传递evidence$1
到的隐含参数classTag[1]()
和classTag[2]()
。因此,它实际上是在将自己与自己进行比较。作为一个变通方案,按照您的建议test2
或预先计算的if
似乎可行。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句