LoginSignup
2
2

More than 3 years have passed since last update.

型の反変と共変は、何故書き込みと読み込みに対応するのか

Last updated at Posted at 2019-06-25

型のvarianceは型の情報のみ持つ時、「アップキャストは可能だがダウンキャストは原則不可能」ということから使い分けが出来る。

アップキャストは可能だがダウンキャストは原則不可能

case class Life(age: Int)
case class Animal(age: Int, size: String) extends Life(age)
case class Human(age: Int, size: String, language: String) extends Animal(age, size)

という継承関係を考える。

AnimalもHumanも、ageをパラメタとして持っているため、Lifeを読み出すことは出来る。
しかしながら、LifeからAnimalを読み出そうと思ったら、sizeおよびlanguageが足らないため(型情報のみからでは)不可

Animal ---> Life    OK
Life   -X-> Animal  NG

矢印は型の変換を表す。
具体的な情報を抽象的な情報に落とすことは出来るが、逆は出来ない。

高校の集合論の記法で書くと、それぞれの集合に対して

Human ⊂ Animal ⊂ Life

の関係が成り立つ。

反変と共変、型の変換元と変換先

上で見た関係より、暗黙的に変換可能な型の関係としては

(具体的) Human ---> Animal ---> Life (抽象的)

となる。

共変

ここで StringなりJsonなり適当なリソースから型Tの値を読み込む Read[T] を仮定する。

このとき、
Read[Human]Humanが得られるが、

Human ---> Animal

より、 Read[Human] は(変換することで) Animal も得ることが出来るため、
Read[Animal]でもあることがわかる。

よって

Read[Human] ⊂ Read[Animal]

したがって、
継承関係

Read[Human] ⊂ Read[Animal] ⊂ Read[Life]

が存在する。

これは

Human ⊂ Animal ⊂ Life

と同じ向きの継承関係となっている(共変)

反変

ここで StringなりJsonなり適当なリソースへ型Tの値を書き込む Write[T] があったとする。
このとき、
Write[Life]Lifeを書き込める。

しかし、

Animal ---> Life

より、 Write[Life] は(変換することで) Animal も書き込むことが出来るため、
Write[Animal] でもある。

したがって、
継承関係

Write[Human] ⊃ Write[Animal] ⊃ Write[Life]

が存在する。

これは

Human ⊂ Animal ⊂ Life

と逆向きの継承関係となっている(反変)

まとめ

以上のように、管理している型から別のものに書き込む際は反変、読み込む場合は共変関係が成り立つ。
そしてそれは型内部でアップキャストは可能だがダウンキャストは原則不可能という関係から導くことが出来る。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2