【Clean Architecture】SOLID原則 - リスコフの置換原則
はじめに
この記事は私が「Clean Architecture 達人に学ぶソフトウェアの構造と設計」を読んだ際の備忘録です。
本記事を読んで興味を持たれたら是非読んでみてください。
本記事では、参考書籍にて語られている「リスコフの置換原則」に関わる部分についてまとめています。
「リスコフの置換原則」とは
「リスコフの置換原則」はこれまでの原則よりも定義が難解で理解しづらいです。
このため、今回は最初からオブジェクト指向プログラミング用に言い換えて述べます。
「リスコフの置換原則」は、「あるクラスTとTのサブクラスSがある時、Tが使用される全ての箇所をSに置換できるようにSを実装するべき」という原則です。
私は「スーパークラスとして扱った時に動作停止や想定外の動作をしないようにサブクラスを実装するべき」という意味だと解釈しています。
「リスコフの置換原則」の例
「リスコフの置換原則」は、オブジェクト指向プログラミングではインターフェースを用いて表現されることがあります。
今回は「リスコフの置換原則」の例として、JavaのListインターフェースとArrayListクラスを見ていきます。
「リスコフの置換原則」が守られている例
Listインターフェースでは以下の機能のメソッド定義があります。
- リスト内の任意の位置に要素を挿入できる
- リスト内の任意の位置にアクセスできる
- リスト内の要素を検索できる
ArrayListクラスでは上記の機能が実装されており、ArrayListインスタンスをListとして扱っても問題なく動作します。
実際にJavaでは以下のようにArrayListインスタンスを生成することがよくあります。
List<E> arrayList = new ArrayList<>();
JavaのListインターフェースとArrayListクラスの関係は上記のような扱いができるため、「リスコフの置換原則」の関係を満たしています。
「リスコフの置換原則」が守られていない例
ここで試しに、リストへの挿入位置が常に先頭になるAlwaysAddHeadListというクラスについて考えてみます。
実装はArrayListとほぼ同じで、挿入のみ指定位置を無視して先頭に挿入するクラスです。
このクラスは、Listインターフェースに対して「リスコフの置換原則」を満たしているでしょうか?
Listインターフェースが要求するメソッドが全て実装されているため、抽象メソッド未実装エラーなどは発生しないと思います。
しかし要素挿入時の動作がListインターフェースの想定と異なっているため、「リスコフの置換原則」の条件は満たされていません。
このように、インターフェースの実装に成功していても「リスコフの置換原則」に違反することがあります。
「リスコフの置換原則」に違反するとどうなるか
「リスコフの置換原則」が守られている場合、サブクラスをスーパークラスとして扱うことができます。
これはクラスをより抽象的に扱えることを意味し、意識すべきことが少なくなることを意味します。
前節のArrayListの例では、ArrayList固有の処理や検索・挿入の実装を意識せずに扱えています。
一方、「リスコフの置換原則」を違反している場合、サブクラスをスーパークラスのように扱えません。
サブクラス固有の振る舞いを意識しないといけなくなってしまいます。
おわりに
ここまで読んでいただきありがとうございます。
次回は、「SOLID原則」の一つである「インターフェース分離の原則」について書く予定です。