函数签名中的Scala继承

函数签名中的Scala继承,scala,inheritance,scala-2.10,Scala,Inheritance,Scala 2.10,我有 然而scala在B的run功能中抱怨 我对方法签名如何工作感到困惑。类B应该有签名X的方法,但类型Y是类型X 谢谢方法的参数类型是相反的。让我以你为例,解释一下: trait X { } class Y extends X Trait A{ def run(x:X){ /////// } } Class B extends A{ def run(y:Y) } 让我用文字表述一下:为了支持A中定义的接口,B需要能够在其运行方法中使用任何X。因此,您无法确定它将得到的X也是Y 请注意

我有

然而scala在B的
run
功能中抱怨

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


谢谢

方法的参数类型是相反的。让我以你为例,解释一下:

trait X {

}

class Y extends X

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

Class B extends A{ def run(y:Y) }
让我用文字表述一下:为了支持
A
中定义的接口,
B
需要能够在其
运行方法中使用任何
X
。因此,您无法确定它将得到的
X
也是
Y

请注意,实际上允许您执行相反的操作:

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
由于
B
在其run方法中接受任何值,因此它也接受
X
,因此一切正常

有趣的是,返回值与此相反:

class B extends A { def run(x: Any) = /* snip */ }
这是有效的,因为
B
只需返回一些
X
。任何
Y
也是
X
,所以我们很好


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

按照您的解释,如果B实现了run(Any),那么B仍然需要实现run(X),因为类a中的run(X)是抽象的。我也尝试了相反的方法,在A中定义一个抽象运行(any),但是如果
B
实现了
run(any)
它已经实现了
run(X)
,那么B将需要运行(any),因为每个
X
也是
any
。因此,方法
run(Any)
也能够处理它
trait A {
  def foo: X
}

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