TL;DR
スーパークラスのオブジェクトをサブクラスのオブジェクトに置き換えても、プログラムが壊れないようにするという原則。強い振る舞い的部分型(behavioral subtyping)の一形態で、SOLID の L にあたる。
なぜ必要か
継承の is-a の関係が見た目上成り立っていても、振る舞いが食い違うと、スーパークラスを前提にしたコードがサブクラスで壊れる。この原則に従えば、型の階層を安心して扱える。
仕組み
Barbara Liskov が 1987 年の基調講演「Data abstraction and hierarchy」で示し、1994 年に Jeannette Wing と論文で定式化した。S が T の部分型なら、T のオブジェクトについて成り立つ性質は S のオブジェクトでも成り立たなければならない。
Wikipedia によると、振る舞いについては次のルールがある。
- 事前条件を強めてはならない
- 事後条件を弱めてはならない
- 不変条件を弱めてはならない
- 履歴制約: スーパータイプが許さない状態の変化を、サブタイプが許してはならない
例
Rectangle を継承した Square は、この原則を破る典型例である。Square は幅と高さを常に等しく保つので、幅を 5、高さを 4 に設定して面積 20 を期待する関数が、Square では失敗する。
注意点
振る舞い的部分型を満たすかは一般には決定不能なので、コンパイラは検査できない。