以下、共変・反変というのはScalaの型パラメータを扱う際用いられる概念のことを言う。
共変と反変をざっくり
共変である型パラメータをもつクラスを扱う際、
型パラメータにサブクラスの型を入れたサブクラスを作成でき
反変である型パラメータをもつクラスを扱う際、
型パラメータに(上とは逆に)親クラスの型を入れたサブクラスを作成出来る
送信と受信
共変と反変の定義は上の通りだが、
何処で差が生まれるかと言うと受け渡しの送信側と受信側どちらを制約するかの差のようだ。
TaPLによるとC#とかだとout, in とかいう直接的な表記で反変・共変を表すらしい。
大は小を兼ねる……本当に?
集合として捉えた場合、親クラスに属する集合の方がサブクラスに属する集合より大きい。
何故なら包含関係があるからだ。
しかし、各クラスを表現するために必要なパラメータ数に着目してみるとどうだろう。
サブクラスは親クラスに必要なパラメータも備え持つため、
親クラスを表現するパラメータ以上のパラメータを持つ。
集合としては小さいサブクラスの方がパラメータとしては多くのものを持つと言えよう。
サブクラスの方が同じか多くのパラメータを持ち、
親クラスとして捉える(アップキャスト)することも出来る。
金銭授受でのアナロジー
以上より、サブクラスは親クラスの代役を出来るが、親クラスはサブクラスの代役を出来きない。
これを金銭のアナロジーで表して、
1100円(サブクラス)は1000円(親クラス)の代役を出来るが、1000円(親クラス)は1100円(サブクラス)の代役を出来ないと表してみる。
自身が金銭を送る(データを送信する)際、
元々1000円送るつもりだった場合、既に1000円送る用意があるため、送る額が減額されても(親クラスになっても)何もしなくて良い。一方、送る額が増額される(サブクラスになる)と困る。
型パラメータを親クラスの型で置き換えられるが逆は出来ないため、これは反変と対応する。
自身が金銭を受取る(データを受信する)際、
元々1000円受け取るつもりだった場合、既に1000円使うつもりにしているため、受け取る額が増額されても(サブクラスになっても)何もしなくて良い。一方、受け取る額が減額される(親クラスになる)と困る。
型パラメータをサブクラスの型に置き換えられるが逆は出来ないため、これは共変と対応する。