SOLID原則のリスコフの置換原則(LSP)についてRubyで解説
プログラミング #ruby #SOLID #オブジェクト指向 #クリーンコードオブジェクト指向プログラミングにおいて、コードの保守性、可読性、再利用性を高めるために、SOLID原則と呼ばれる5つの重要な設計原則があります。
今回は、このSOLID原則のうち、リスコフの置換原則 (Liskov Substitution Principle, LSP)についてRubyのサンプルコードを用いて解説していきます。
目次 / Index
SOLIDとは
SOLIDとは、5つの原則の頭文字を取った略語です。
- Single Responsibility Principle(SRP): 単一責任原則
- Open Closed Principle(OCP): オープン・クローズドの原則
- Liskov Substitution Principle(LSP): リスコフの置換原則
- Interface Separation Principle(ISP): インターフェース分離の原則
- Dependency Inversion Principle(DIP): 依存性逆転の原則
リスコフの置換原則 (Liskov Substitution Principle, LSP)とは
リスコフの置換原則は、派生クラスのオブジェクトが基底クラスのオブジェクトと置換可能であるべきだという原則です。
つまり、派生クラスは基底クラスのメソッドと同じ引数/返り値の種類を保証し、基底クラスの代わりに使用できるようにします。
これにより、オープン・クローズドの原則に則ったコードで記載した抽象クラスを引数にとる処理で、抽象クラスに属する具象クラスを別のものに変えたとしても問題なく動作し、クラスの再利用性が高まります。
リスコフの置換原則に違反しているコード
以下のPost
とDraftPost
クラスを例にします。
class Post
def initialize(title, content)
@title = title
@content = content
end
def title
@title
end
def content
@content
end
def publish
puts "Post published: #{@title}"
true
end
end
class DraftPost < Post
def publish
raise "Cannot publish a draft post"
end
end
こちらDraftPost
が基底クラスであるPost
のpublish
メソッドと異なる返り値を返しています。
これでは、Post
クラスを期待している箇所で、DraftPost
が渡されるとエラーとなります。
これでは、再利用性がなく、DraftPost
固有の処理を書かないといけません。
リスコフの置換原則に則ったコード
以下が則ったコードとなります。
class Post
def initialize(title, content)
@title = title
@content = content
end
def title
@title
end
def content
@content
end
def publish
puts "Post published: #{@title}"
true
end
end
class DraftPost < Post
def publish
puts "Cannot publish a draft post"
false
end
end
DraftPost
のpublish
は基底クラスであるPost
と同じくboolean
を返すようになりました。
これにより使う側はPost
クラス、DraftPost
クラスのどちらが渡されてもエラーとなることなく、問題なく処理を続行することが出来ます。
最後に
リスコフの置換原則を使用することで、クラスの再利用性を高めることが出来ます。
また、他のクラスの機能を使いたいためだけにis-a
の関係でないのに継承をしてしまうような初心者が最初やってしまいがちなアンチパターンも避けることが出来ます。
もし継承とすべきか委譲とすべきかの判断に迷った際は、この原則を思い出すことで、適切な判断の助けになるかもしれません。
次回はインターフェース分離の原則(ISP)について記事を書こうと思います。