函数签名中的 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
,所以我们很好。
我希望这能让大家更清楚这里发生了什么,以及为什么编译器禁止您以这种方式实现您的方法。
我有
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
,所以我们很好。
我希望这能让大家更清楚这里发生了什么,以及为什么编译器禁止您以这种方式实现您的方法。