項目 16: 継承よりコンポジションを選ぶ
継承を避けておきたい理由
あるサブクラスはスーパークラスの実装に依存してしまうため。 スーパークラスの実装が変わったら、サブクラスの実装も追随して書き換えなければならない。
解決法:コンポジション
コンポジションとは、あるクラスを継承する代わりに、そのクラスを private
のフィールドとして持たせたクラスを作ることである。
新たなクラスのメソッド内では、保持しているクラスの対応するメソッドを利用しつつ(転送)、新たな処理も加える。
項目 17: 継承のために設計および文書化する、でなければ継承を禁止する
項目 16 でも述べられていたように、サブクラスはスーパークラスの実装に依存する。
スーパークラスではオーバーライドできるメソッドについて、そのクラス自身がどう利用しているかをドキュメント化しておく必要がある。
protected
でメソッドを提供する必要があるかもしれない
継承可能なクラスをテストするためには、2, 3 個のサブクラスを書いてみるしかない。
コンストラクタ内でオーバーライド可能なメソッドを利用してはならない。
なぜなら、スーパークラスのコンストラクタ内でオーバーライドされているメソッドを呼び出すと、サブクラスのメソッドが呼び出されるからである。
サブクラスのコンストラクタは、スーパークラスのコンストラクタのあとに呼び出される。
よって、サブクラスのメソッドがサブクラスのコンストラクタでの処理に依存していると、うまくいかなくなる。
これは、clone
, readObject
のようなオブジェクトを生成するメソッドにおいても同様である。
サブクラス化したいなら安全な設計をする必要がある。
継承禁止するならクラス宣言に final
を付けるか、static ファクトリーメソッドを実装する。
参考文献
EFFECTIVE JAVA 第2版 (The Java Series)
- 作者: Joshua Bloch,柴田芳樹
- 出版社/メーカー: 丸善出版
- 発売日: 2014/03/11
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (12件) を見る