#IDisposableの第2回はちょっと待って。
オブジェクト指向の重要な原則の一つに、「リスコフの置換原理」がある。
基本的なことなので、知らない人はぜひこの機会に調べて身につけてほしいが、ここでも簡単に説明しよう。
極めて簡潔に言えば、「型Tのオブジェクトを使用できるところではどこでも、Tの派生型を使用できなければならない」というのが、この原則だ。
よく例に出されるのは、「型Tのオブジェクトを引数に取るメソッドには、Tの任意の派生型のオブジェクトを渡せなければならない」というやつ。
だが、これは引数にとどまらない。
戻り値についても同じことが言える。つまり「型Tのオブジェクトを戻り値として返すメソッドは、Tの任意の派生型を返せるようになっていなければならない」だ。
この制約が課される対象は2つある。
例示では、型Tと、その派生型にしか言及されない場合が多い。つまり、「Tの派生型は、T型のオブジェクトの代わりに使われても問題ない作りになっていなければならない」ということだ。これが1つ。
もう1つは、それを受け取る側だ。引数を例にすれば、「型Tのオブジェクトを引数に取るメソッドは、Tの任意の派生型を受け取っても正しく動作しなければならない」。
即ち、リスコフの置換原理は、以下の4つ(例外にも言及する場合は2つ加えて6つ。プロパティは割愛)の場合に成り立つ。
- 型Tから派生した型Sのオブジェクトは、型Tのオブジェクトを引数に取るメソッドに渡しても正しく動作しなければならない。
- 型Tから派生した型Sのオブジェクトは、型Tのオブジェクトを戻り値として返すメソッドから返されても、正しく動作しなければならない。
- 型Tのオブジェクトを引数に取るメソッドは、Tから派生した型Sのオブジェクトを渡されても、正しく動作しなければならない。
- 型Tのオブジェクトを返すメソッドの呼び出し側は、Tから派生した型Sのオブジェクトを返されても、正しく動作しなければならない。
引数や戻り値を受け取る側については例示が少ないため、適用されないと思っていたら間違いだ。
そして、受け取る側についても成り立つということは、「(特別な場合を除き)受け取る側は、受け取った引数や戻り値をダウンキャストしてはならない」ということになる。