Chapter 6 - Practical Object Oriented Design in Ruby
Acquiring Behavior Through Inheritance
まとめ
継承とはメッセージを自動的に転送すること。
継承を用いると、クラスの構造が複雑になるので、必要な情報が揃った時に行うのがいい。
具体的には、2つの似たような種類のクラスがあって、1つの親クラスと、2つのサブクラスに分けられそうな場合は、いくつかコードが重複してしまっていても、そのままにしておいた方がいい。(もちろんケースバイケース)
似たような属性を持つクラスが3つになった時には、親子構造を作成するための情報をかなり持つことができるので、適切な設計を作りやすくなる。(必要な情報が入るまで、現状のままにしておくことは、コストマネージメントを考える上で大事)
いざ親クラスを作ろうとなった時は、まず空の親クラスを作成し、継承関係を設定した後に、サブクラスから親クラスへ振る舞いをボトムアップさせていくやり方がいい。
この方法の場合は、サブクラスに抽象化すべきところが残ってしまう可能性がある。
ただ、抽象化しないとサブクラス間でコードが重複してしまう→親クラスにまとめるというのは自然に行われていくので、それほど大きな問題にはなりにくい。
逆の場合、先に親クラスに元のクラスをコピーし、サブクラス固有の振る舞いをサブクラスに移行するやり方の場合は、親クラスに本来サブクラスであるべき具体的な振る舞いが残ってしまう可能性がある。
このケースを修復するのは前者より難解になりやすく、親クラスに手をつけずにコードを拡張していくと、純粋な継承関係が崩壊してしまい、システム全体へと影響が広がってしまう可能性がある。
サブクラスからsuperを使って明示的に親クラスのメソッドを呼び出すのは、1つの依存性と言える。 依存性があるということは、変更時のコストに影響がある。
hookやtemplate patternなどを使うことで、依存性を避けるように、サブクラスのスペシャリティーを簡潔に表現できる設計方法を探すといい。