この記事は「オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方」を読んだまとめです。
継承
継承はあるメッセージに応答できなければ、他のオブジェクトにそのメッセージを移譲する動きをする
スーパークラス(抽象クラス)はサブクラス間で共有される振る舞いの共有する格納場所を提供する。サブクラスがそれぞれに特化したものを用意する。いきなりスーパークラスを作るのではなく、サブクラスになり得るクラスが複数ある場合、共通の振る舞いを確認してスーパークラスに昇格する形で継承関係を作るようにする。
共通の振る舞いはスーパークラスに定義して、サブクラスで固有の振る舞いを定義する。以下の例では、サブクラスはdefault_tire_sizeを実装しているが、default_chainは実装していない。タイヤのサイズはサブクラスで定義する必要があるが、チェーンのサイズは共通しているのでスーパークラスで定義されている。(「テンプレートメソッド」パターン)
default_tire_sizeが定義されていない時にエラーを発生させることで、default_tire_sizeが定義されていないサブクラスが作られることを防いでいる。
sparesメソッドはスーパークラスで共通する値を定義して、サブクラスでそれぞれ特化した値をマージしている。オブジェクトのクラスを確認し、どのようなメッセージをそのオブジェクトに送るか決める、自分の分類を保持する変数などを確認して、自身に送るメッセージを変えるこのパターンは、相手が誰だか知っているから、特定のメッセージを送る状態であり依存関係が生まれているので注意が必要。
class Bicycle
attr_reader:size,:chain,:tire_size
def initialize(args={})
@size = args[:size]
@chain = args[:chain] || default_chain
@tire_size = args[:tire_size] || default_tire_size
end
def spares
{tire_size:tire_size,
chain:chain}
end
def default_chain
'10speed'
end
def default_tire_size
raise NotImplementedError
end
end
class RoadBike < Bicycle
attr_reader:tape_color
def initialize(args)
@tape_color = args[:tape_color]
super(args)
end
def spares
super.merge({tape_color:tape_color})
end
def default_tire_size
'23'
end
end
class MountainBike < Bicycle
attr_reader:front_shock,:rear_shock
def initialize(args)
@front_shock = args[:front_shock]
@rear_shock = args[:rear_shock]
super(args)
end
def spares
super.merge({rear_shock:rear_shock})
end
def default_tire_size
'2.1'
end
end