scala – 函数在其参数类型中是逆变的,在返回类型中是共变量
在发布此问题之前,我已经阅读了
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? } 如上所述,在测试2中,为什么我可以使用法拉利作为参数成功调用test2,并且以汽车作为参数不成功? 语句Function是否在其参数类型中是逆变的,并且返回类型中的co-variant仅适用于作为参数传递的函数?我想我没有在声明和我写的2个测试之间做出适当的区分. 解决方法
那是因为你将子类型与co / contravariance混合在一起.
在你的第一个例子中,你期望一个Function1 [-T,R].在这种情况下,共同/逆转规则适用于功能类型.在第二个示例中,您遵循简单的子类型规则. 在test1中,传入foo1,即Car =>法拉利一切正常,因为foo1期待一辆车,但得到一辆运动车,这是一辆车.由于子类型的性质,任何需要Car的方法都可以处理子类型.但是当我们单独讨论子类型时,这些规则不起作用. 如果我们用foo1用实际类型扩展test1,也许它会更清晰: foo1: >参数类型: >期望:汽车 >返回类型: >期望:SportsCar 一切顺利. 在test2中,规则发生了变化.如果我期待一辆跑车通过任何车,那么我就不能再依赖于跑车的输入而且一切都会中断,但是如果你通过一辆实际上是跑车的法拉利,一切都很好. 再次,让我们排列类型: 测试2: >第一种情况: >参数类型: >期望:SportsCar >结果:大家都很开心 >第二种情况: >参数类型: >期望:SportsCar >结果:错误.我们不确定汽车是一辆真正的跑车. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |