【发布时间】:2017-05-13 13:54:10
【问题描述】:
在发布这个问题之前,我已经阅读了this 和this 的答案,但我对这个主题的理解仍然有点不清楚,如下所述:
我理解协变和逆变独立的含义。
如果我有以下课程:
class Car {}
class SportsCar extends Car {}
class Ferrari extends SportsCar {}
还有:
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?
}
如上所述,在Test 2中,为什么我可以以ferrari为参数调用test2成功,而以a car为参数调用失败?
函数的参数类型是逆变的,返回类型是协变的语句是否只适用于作为参数传递的函数?我想我没有在语句和我编写的 2 个测试之间做出适当的区分。
【问题讨论】:
-
test2与test1没有太大关系。第一个检查functions 本身的子类型关系,第二个检查普通旧类的子类型。 -
通过使你的类层次结构你说每个
FerrariIS-ASportsCar,它应该被这样对待。这就是为什么你可以在考虑基类时传递一个特定的类,但不能反过来,就像最后一行一样。
标签: scala covariance contravariance