参数化类中的类型不匹配 - 但为什么?

时间:2012-07-04 12:53:52

标签: scala types

假设我们有以下定义:

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)
                            ^

我不明白,这里有什么问题,因为变量bt是同一个对象而tT类型的对象?

或许,编译器确实将变量b视为新的变量(没有与t的关系)。然后,bA的子类型,但不一定是T的子类型,因为T可以是A的任意子类型。这是正确的解释吗?

2 个答案:

答案 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,因此类型不匹配。

不幸的是,即使您没有引入新的类并密封层次结构,编译器似乎也不关心它,或者可能有其他我不知道的合理投诉。