18

共分散と反分散という用語を理解しています。しかし、私が理解できない小さなことが1つあります。coursera の「Functional Programming in Scala」コースで、Martin Ordersky は次のように述べています。

関数は引数の型で反変であり、戻り値の型で共変です

たとえば Java では、 let Dogextends Animal. 関数を次のようにします。

void getSomething(Animal a){

そして私は関数呼び出しを持っています

Dog d = new Dog();
getSomething(d)

つまり、基本的に何が起こっているのかということAnimal a = dです。そしてウィキの共分散によると、「広いものから狭いものへの変換」です。上記では、dog から Animal に変換しています。SO は、反変ではなく共変の引数の型ではありませんか?

4

4 に答える 4

32

Scala で関数を定義する方法は次のとおりです。

trait Function1 [-T1, +R]  extends AnyRef

英語では、パラメーターT1は反変であり、結果の型Rは共変です。どういう意味ですか?

一部のコードで型の関数が必要な場合、パラメーターの反変性のおかげDog => Animalで型の関数を指定できます (より広い型を使用できます)。Animal => Animal

またDog => Dog、結果の型の共分散のおかげで、型の関数を提供できます (より狭い型を使用できます)。

これは実際に理にかなっています。誰かが犬を任意の動物に変換する関数を必要としています。任意の動物 (犬を含む) を変換する関数を提供できます。また、関数は犬のみを返すことができますが、犬はまだ動物です。

于 2012-11-10T12:27:02.027 に答える
4

に変換DogすることAnimalは、狭いものから広いものに変換することであるため、共分散ではありません。

于 2012-11-10T12:15:17.440 に答える
1

2007年にScalaBookを読んでいたとき、その文に混乱したことを覚えています。Martinは、言語機能について話しているかのようにそれを提供しますが、その文では、機能全般についての事実しか述べていません。Scalaは、具体的には、その事実を通常の特性によって単純にモデル化します。Scalaには宣言サイトの差異があるため、これらのセマンティクスを表現することは言語にとって自然なことです。

一方、Java Genericsは使用サイトの分散のみをサポートするため、Javaの関数型の共変性に最も近いのは、各使用サイトでそれを手動でコーディングすることです。

public int secondOrderFunction(Function<? super Integer, ? extends Number> fn) {
     ....
}

Function<P, R>(適切に宣言されたインターフェースを想定し、Pパラメーター型とR戻り型を表します)。当然、このコードはクライアントの手にあり、関数にまったく固有ではないため、paramタイプ/リターンタイプの差異に関するステートメントは、Javaのどの言語機能にも適用できません。これは、機能の性質に関して、より広い意味でのみ適用可能です。

Java 8はクロージャを導入します。これはファーストクラスの関数を意味しますが、以下のJörgのコメントによると、実装には本格的な関数型は含まれません。

于 2012-11-10T12:21:27.270 に答える