3

効果的な 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 トレイトに適用されないのはなぜですか?

4

2 に答える 2

6

Joshua は正しいし、Scala も正しい。実際、Scala ではこの規則が義務付けられているため、気にする必要はありません。Java にはバリアンス アノテーションがなく、コール サイトでの存在を処理する必要があるため、正しい設計についてプログラマーをガイドする必要があります。

Scala には定義サイトにバリアンス アノテーションがあり、Java には呼び出しサイトに存在情報があります。呼び出しの出力は定義の入力であり、その逆も同様です。

AFunction1は、パラメーターから読み取ったり、結果に書き込んだりしていません。これはreduce、ジョシュアの例で行っていることです。代わりに、コレクションFunction1 として考える必要があります。

コレクションに書き込むと、そのコレクションはコンシューマーになります。関数と同様に、関数を呼び出すと、関数に書き込みます。したがって、書き込まれる入力パラメータは反変でなければなりません。

同様に、コレクションから読み取る場合、そのコレクションはプロデューサーです。結果を見て関数を読み取るため、出力パラメーターは共変でなければなりません。

ご覧のとおり、まさにFunction1表記です。

于 2012-07-01T02:35:27.437 に答える
5

のワイルドカードはfunc、メソッドに渡される型に適用されます。これらは、任意の ArrayList を入力として渡すことができArrayList<Object>ArrayList<Number>または またはArrayList<Integer>を出力として渡すことができることを意味します。メソッド自体は一般的ではありません。

scala Function1 型では、分散が型に適用されるためFunction1[AnyRef, Integer]、 a が必要な場所で a を使用できますFunction[AnyRef, Number]

于 2012-06-30T10:33:06.517 に答える