共変性と反変性(Covariance and Contravariance)

共変性と反変性(Covariance and Contravariance)・・・と言われても言葉だけだとなんのことだかよくわからないと思います。

もともとは数学の概念で、プログラミング言語にも取り入れられました。
[Link]「Covariance and contravariance (computer science) - Wikipedia, the free encyclopedia」 http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)
[Link]「共変性と反変性 - Wikipediahttp://ja.wikipedia.org/wiki/%E5%85%B1%E5%A4%89%E6%80%A7%E3%81%A8%E5%8F%8D%E5%A4%89%E6%80%A7
Wikipediaを見ても小難しいことが書かれてる印象を受けるかもしれません。

C#VB.NETなどのMicrosoft .NET Framework言語でも、いくつかのジェネリックインターフェイスは共変性と反変性が成り立つように適切に定義されています。
[Link]「ジェネリックの共変性と反変性」 http://msdn.microsoft.com/ja-jp/library/dd799517.aspx
このページもなかなか小難しいことが書いてあるように見えるかもしれません。

共変性と反変性は、ある集合Aから構成された別の集合Bに関して、元の集合Aの中の関係から、別の集合Bの中の関係がごく「自然に」「直観的に」成り立つというものです。

たとえば、説明に好都合な例としてConverterインターフェイスがあります。何かXを何かYに変換する装置の集合と考えることができます。

[Link]「Converter(TInput, TOutput) デリゲート (System)」 http://msdn.microsoft.com/ja-jp/library/kt456a2y.aspx
TInputに対して、Converter(TInput, TOutput)は反変性が成り立ちます。
TOutputに対して、Converter(TInput, TOutput)は共変性が成り立ちます。


つまり、TInputをより一般的な型に置き換えても、Converter(TInput, TOutput) の要素とみなせるということと、TOutputをより具体的な型に置き換えても、Converter(TInput, TOutput) の要素とみなせるということです。

具体的に考えるとそれが成り立つのが自然であることがわかります。

  • 猫を何かに変換する装置の一種として、動物を変換する装置が含まれるのは自然です。動物を変換する装置で猫を変換できるからです。
  • また、何かを動物に変換する装置の一種として、何かを人間に変換する装置が含まれるのは自然です。人間も動物の一種だからです。

集合式で書くと
動物 ⊇ 猫  → 動物を何かに変換する装置 ⊆ 猫を何かに変換する装置 (反変性)
人間 ⊆ 動物 → 何かを人間に変換する装置 ⊆ 何かを動物に変換する装置 (共変性)

実際、左側の関係から、右の関係も成り立つのがごく自然と考えられます。また、前者は、包含関係を反転するので「反変性」、後者は包含関係を保存するので「共変性」と呼ばれます。

プログラミング言語インターフェイスでこれが適切に実装されていると、直観的にスムーズにプログラミングを作成することができます。
たとえば、以下のC#コードですが、

    public class Base { }
    public class Derived : Base { }
    class Program
    {
        static void Main(string[] args)
        {
            Converter<Derived, string> conv =
                (Converter<Base, string>)(x => x.GetType().Name);
        }
    }

Visual Studio 2008(C#3.0)でエラーとなりますが、Visual Studio 2010(C#4.0)ではエラーにはなりません。自然に反変性が成り立つように改善されています。