函数签名中的 Scala 继承

Scala inheritance in function signature

我有

trait X {

}

class Y extends X

Trait A{ def run(x:X){ /////// } }

Class B extends A{ def run(y:Y) }

但是 scala 抱怨 B 的 run 函数

我对方法签名如何继承感到困惑。 class B 应该有签名 X 的方法,但是类型 Y 是类型 X。

谢谢

方法的参数类型是逆变的。让我举个例子解释一下:

val b: B = new B
val y: Y = new Y

b.run(y) // everything is ok

val a: A = b // B is A
val x: X = new X {}

a.run(x) // run on A takes an X. x is of type X
// But: B only takes a Y (more specific type) --> Boom

让我用文字表述:为了支持 A 中定义的接口,B 需要能够与 any X 在其 run 方法中。所以你不能确定它要得到的 X 也是 Y.

请注意,您实际上可以做相反的事情:

class B extends A { def run(x: Any) = /* snip */ }

由于 B 在其 运行 方法中接受任何值,它也接受 X,所以一切都很好。

有趣的是,return 值是相反的:

trait A {
  def foo: X
}

class B extends A {
  def foo: Y = /* snip */
}

这是有效的,因为 B 只需要 return 一些 X。任何Y也是一个X,所以我们很好。

我希望这能让大家更清楚这里发生了什么,以及为什么编译器禁止您以这种方式实现您的方法。