Scala:为什么PECS原则不适用于Function1?

时间:2012-06-30 08:51:52

标签: scala

在Effective Java中,Joshua Bloch讨论了PECS(Producer-Extends,Consumer-Super)的原理。

我对此的理解是,为了提高API灵活性,输入(产生的集合)应该是协变的,输出(消耗的集合)应该是逆变的。

实现此原则的函数可以具有以下签名:

private static void func( ArrayList<? extends Object> input, ArrayList<? super Integer> output)

但是,在Scala中,Function1特征具有以下签名:

trait Function1[-T1, +R] extends AnyRef

T1(输入类型)是逆变的,而R(输出类型)是协变的。

我的理解是否正确?如果是这样,为什么PECS不适用于Scala的Function1特性?

2 个答案:

答案 0 :(得分:6)

约书亚是对的,斯卡拉也是如此。实际上,Scala强制要求这个规则,所以你不必担心它。 Java,因为它没有方差注释,必须在调用站点处理存在感,需要它们指导程序员进行正确的设计。

Scala在定义网站上有方差注释,而java在调用网站上有存在感。调用的输出是定义的输入,反之亦然。

Function1未读取其参数或写入其结果,这是reduce在Joshua的示例中所做的事情。相反,您必须将Function1 视为集合。

当您写入集合时,该集合是消费者。与函数类似:当你调用它时,你正在写它。因此,正在写入的输入参数必须是反变量的。

同样,当您从集合中读取时,该集合是生产者。您通过查看其结果来读取函数,因此输出参数必须是共变量。

如您所见,这正是Function1符号。

答案 1 :(得分:5)

func上的通配符适用于传递给方法的类型。它们意味着可以传递任何ArrayList以进行输入,并且可以传递ArrayList<Object>ArrayList<Number>ArrayList<Integer>以进行输出。该方法本身并不通用。

使用scala Function1类型时,方差适用于类型,因此Function1[AnyRef, Integer]可用于需要Function[AnyRef, Number]的位置。

相关问题