3

假设我们有以下定义:

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。这是正确的解释吗?

4

2 回答 2

3

case b: B实际上会产生如下代码:

if(t.isInstanceOf[B]) {
  val b = t.asInstanceOf[B]
  // ...
}

所以b不是t。它仍然引用同一个实例,但是bisB和 not的类型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])
于 2012-07-04T13:02:04.737 回答
0

您对编译器说,您需要T成为 的A所有可能值的子类型,T但要给出 的非常具体的子类型A,即Bto foo。如果你有一个Test[C]with class C extends Bfoo期望得到 aC但得到 aB所以类型不匹配。

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

于 2012-07-04T14:28:32.803 回答