rga*_*ber 9 scala covariance contravariance
在发布这个问题之前,我已经阅读了这个和这个答案,但我对这个主题的理解仍然有点不清楚,如下所述:
我理解协变和逆变独立意味着什么.
如果我有以下课程:
class Car {}
class SportsCar extends Car {}
class Ferrari extends SportsCar {}
Run Code Online (Sandbox Code Playgroud)
和:
object covar extends App {
// Test 1: Works as expected
def test1( arg: SportsCar => SportsCar ) = {
new SportsCar
}
def foo1(arg: Car): Ferrari = { new Ferrari }
def foo2(arg: SportsCar): Car = { new Ferrari }
def foo3(arg: Ferrari): Ferrari = { new Ferrari }
test1(foo1) // compiles
test1(foo2) // Fails due to wrong return type - violates return type is covariant
test1(foo3) // Fails due to wrong parameter type - violates param type is contravariant
// Test 2: Confused - why can I call test2 succesfully with ferrari
// as the parameter, and unsuccesfully with a car as the parameter?
def test2(arg: SportsCar): SportsCar = {
new Ferrari
}
val car = new Car()
val sportsCar = new SportsCar()
val ferrari = new Ferrari()
val f1 = test2(ferrari) // compiles - why?
val f2 = test2(car) // fails - why?
}
Run Code Online (Sandbox Code Playgroud)
如上所述,在测试2中,为什么我可以用法拉利作为参数成功调用test2,并且以汽车作为参数不成功?
语句Function是否在其参数类型中是逆变的,并且返回类型中的co-variant仅适用于作为参数传递的函数?我想我没有在声明和我写的2个测试之间做出适当的区分.
那是因为你将子类型与co/contravariance混合在一起.
在你的第一个例子中,你期待一个Function1[-T, +R]
.在这种情况下,共同/逆转规则适用于功能类型.在第二个示例中,您遵循简单的子类型规则.
在test1
,你传入的地方foo1
,Car => Ferrari
一切都有效,因为foo1
期望一个Car
,但得到一个SportsCar
,这是一个Car
.Car
由于子类型的性质,任何需要处理子类型的方法.但是当我们单独讨论子类型时,这些规则不起作用.
如果我们test1
用foo1
实际类型扩展,也许它会更清楚:
Car
SportsCar
SportsCar
Ferrari
一切顺利.
在test2
规则改变.如果我希望SportsCar
你通过任何一辆车,那么我就不能再依赖于跑车的输入而且一切都会破裂,但是如果你通过一辆实际上是跑车的法拉利,一切都很好.
再次,让我们排列类型:
SportsCar
Ferrari
子类型)SportsCar
Car
归档时间: |
|
查看次数: |
1241 次 |
最近记录: |