假设我们有以下定义:
abstract class A
class B extends A
trait Test[T <: A] {
def foo(t: T) = println("I'm Foo")
def bar(t: T) = t match {
case b: B => foo(b)
case _ => println("Bar says: Other")
}
}
Scala编译器会抱怨错误:
<console>:14: error: type mismatch;
found : b.type (with underlying type B)
required: T
case b: B => foo(b)
^
我不明白,这里有什么问题,因为变量b
与t
是同一个对象而t
是T
类型的对象?
或许,编译器确实将变量b
视为新的变量(没有与t
的关系)。然后,b
是A
的子类型,但不一定是T
的子类型,因为T
可以是A
的任意子类型。这是正确的解释吗?
答案 0 :(得分:3)
case b: B
实际上会产生如下代码:
if(t.isInstanceOf[B]) {
val b = t.asInstanceOf[B]
// ...
}
所以b
不是t
。它仍然引用相同的实例,但b
的类型为B
而不是T
。同样的事情:
def foo(x: String) = println(x)
foo("Foo bar".asInstanceOf[AnyRef])
<console>:9: error: type mismatch;
found : AnyRef
required: String
foo("Foo bar".asInstanceOf[AnyRef])
答案 1 :(得分:0)
您对编译器说,您需要T
作为A
的所有可能值的T
子类型,但要提供非常具体的A
子类型,即{ {1}}到B
。
如果您的foo
Test[C]
class C extends B
,则foo
会获得C
,但会获得B
,因此类型不匹配。
不幸的是,即使您没有引入新的类并密封层次结构,编译器似乎也不关心它,或者可能有其他我不知道的合理投诉。