我理解协方差和对方差这两个术语。但有一件小事我无法理解。在coursera的“Scala中的函数编程”课程中,Martin Ordersky提到:
函数在其参数类型中是反向变量,在返回类型中是协变量。
例如,在Java中,让Dog扩展Animal。让一个功能是:
void getSomething(Animal a){我的函数调用为
Dog d = new Dog();
getSomething(d)所以从根本上说,发生的是Animal a = d。根据维基的说法,协方差是“由宽变窄”。在上面,我们从狗变成动物。所以,论点类型不是协变的,而不是反变的吗?
发布于 2012-11-10 12:27:02
我是Scala中函数的定义
trait Function1 [-T1, +R] extends AnyRef在英语中,参数T1是反变的,结果类型R是协变的。什么意思?
当某些代码需要一个Dog => Animal类型的函数时,您可以提供一个Animal => Animal类型的函数,这要归功于参数的对比变化(您可以使用更广泛的类型)。
还可以提供Dog => Dog类型的函数,这要感谢结果类型的协变性(您可以使用更窄的类型)。
这实际上是有道理的:有人想要一个功能,把狗变成任何动物。你可以提供一个转换任何动物(包括狗)的功能。此外,你的功能只能返回狗,但狗仍然是动物。
发布于 2012-11-10 12:15:17
将Dog转换为Animal是从窄到宽的转换,所以它不是协方差。
发布于 2012-11-10 12:21:27
我记得我在2007年读Scala书的时候被这句话弄糊涂了。马丁把它说得好像在说语言功能,但在这句话中,他只说了一个关于一般功能的事实。具体来说,Scala简单地通过一个常规特征来建模这个事实。因为Scala有声明-站点的差异,表达这些语义对语言来说是很自然的。
另一方面,Java泛型只支持使用站点方差,因此在Java中最接近函数类型协/反方差的方法是在每个使用站点对其进行手工编码:
public int secondOrderFunction(Function<? super Integer, ? extends Number> fn) {
....
}(假设一个适当声明的接口Function<P, R>,P代表参数类型,R代表返回类型)。当然,由于这段代码掌握在客户端,而且根本不特定于函数,所以关于param类型/返回类型差异的语句不适用于Java的任何语言特性。它只在更广泛的意义上适用,涉及职能的性质。
Java 8将引入闭包,这意味着有一流的函数,但是,根据J rg下面的评论,实现将不包括一个成熟的函数类型。
https://stackoverflow.com/questions/13321921
复制相似问题