共変性と反変性 (計算機科学)
ここでパラメータ型をCat <: Animalとし、リターン型を獣人 <: 動物とすると、その関数の型では、(Cat->獣人) <: (Animal->動物)よりも、(Animal->獣人) <: (Cat->動物)の方が、型安全という結論になっている。この辺りは代数学からの考え方になっている。
これはジェネリック関数でも用いられて、S func[-T, +S] (T x, T y) { ... } のように構文化される。-は反変記号、+は共変記号である。関数funcの各インスタンスは、型引数を反映したサブタイプ関係で結ばれる。
一般的な規則は以下となる。
( P 1 → R 1 ) ≤ ( P 2 → R 2 ) {\displaystyle (P_{1}\rightarrow R_{1})\leq (P_{2}\rightarrow R_{2})} if P 1 ≥ P 2 {\displaystyle P_{1}\geq P_{2}} and R 1 ≤ R 2 {\displaystyle R_{1}\leq R_{2}} .
推論規則の記法を使うと以下のように書ける。
P 1 ≥ P 2 R 1 ≤ R 2 ( P 1 → R 1 ) ≤ ( P 2 → R 2 ) {\displaystyle {\frac {P_{1}\geq P_{2}\quad R_{1}\leq R_{2}}{(P_{1}\rightarrow R_{1})\leq (P_{2}\rightarrow R_{2})}}}
一般的に、結果の型は共変である。
オブジェクト指向プログラミングにおいては、サブクラスでメソッドをオーバーライドした場合、置換が暗黙的に行われる。すなわち、元のコードで古いメソッドを呼び出すと、新しいメソッドが代わりに実行される。どのような形式のオーバーライドを許容するか、オーバーライドされたメソッドの型がどのように変化するかは、プログラム言語によって様々である。
クラスにおける型の同等性は、継承の階層関係によって暗黙的に示される (そしてこれこそが、継承を行う正当な理由である)。しかしながら、派生クラスでの変更によってはこの表明に違反する可能性があるため、プログラミング言語のなかには、特定の状況下でのこの暗黙の同等性に関する前提を限定するものもある。
C# 3.0 の総称型パラメータは共変性も反変性もサポートしていない。IEnumerable<TypeDerivedFromA> は IEnumerable<A> に代入できそうにみえるが、代入可能でない。C# 4.0 ではこれがサポートされるようになった。なお、普通の配列型は、.NET の導入以来、常に共変性と反変性をサポートしつづけている (厳密に保証されているわけではない。配列の代入が正当に行われても、実行時に例外が発生する可能性がある)。