リスコフの置換原則は呼び出し側にも責任が伴う

以前にオブジェクト指向になっているならば、あるクラスを継承したクラスは継承元のクラスと置き換えても動かなければならないという気付きについて書きました。名前がついていて、それはリスコフの置換原則と呼ばれるらしいです。

fj.hatenablog.jp

このリスコフの置換原則を守るには、使われる側のクラスだけでなく、使う方も気をつけなければならないことがあると気がつきました。

継承というのは、クラスの意味は変えずに、振る舞いを変えることです。継承して、メソッドをOverrideすれば当然メソッドの振る舞いは変わります。

そうであれば、呼び出し元は継承元クラスの細かい振る舞いに依存してはならないことになります。派生クラスでメソッドの振る舞いが変わったときに、置換可能ではなくなるからです。

派生クラスがメソッドのOverrideを行わずにメソッドを増やすだけなら、特にこの問題は起きません。Overrideというメソッドをつけかえるようなことをする場合に起こることですが、呼び出し元が派生クラスがメソッドをOverrideしているかどうかなんて分からないことです。したがって、Overrideされていても大丈夫なようにしておかなければならない。

ある共通の性質をもったものの集まりをクラスといいます。クラスの利用者はその共通の性質だけを期待して、クラスを利用しなければならないということになります。継承する側が共通の性質から外れるようなことをしてはいけないというのは、派生クラスを提供する側の責任です。一方で、共通の性質以外を期待してはいけないのは呼び出し側の責任になります。

共通の性質というのは、つまりクラスの仕様になるかと思う。Javadocに記述される内容です。

呼び出し元は、Javadocに記述されていないようなことを期待しては行けないということになります。つまり、具体的な実装に依存する振る舞いを知った上でそれを期待するということは誤りです。ソースコードを読んでもよいが、読まなければ分からないようなことを利用してはいけないということになる。呼び出され側の仕様外の動きが変わって、呼び出し側が動かなくなっても、それは呼び出し側が悪いという話になります

呼び出し側が呼び出され側に期待してよい振る舞いを規定しておくことは、呼び出され側のクラスを作る人がやらなければならないことなる。こういう視点に立つと、仕様とは何なのか、Javadocに何を書くべきかというのが分かってきます。