実はまじめに通して読んだことがないので、読んでて気になったところを中心にメモっていく。
本題。
下手に継承しちゃうと親クラスの実装に影響されてしまう。
親クラスの実装を熟知していないと、思わぬ副作用を招くことがある。
例えば以下のような感じだ。
まず子クラス。
public class SampleChild extends SampleParent { public static void main(String[] args) { new SampleChild().hi(); } @Override public void say() { System.out.println("Child#say"); super.say(); } @Override public void hi() { System.out.println("Child#hi"); super.hi(); } }次に親クラス。
public class SampleParent { public void say() { System.out.println("Parent#say"); } public void hi() { this.say(); } }これで、SampleChild#hi() を呼ぶとする。
とするとまず親のhi() が呼ばれるけど、これは内部的には SampleParent#say() が呼び出されることになっている。
で、このメソッドは子によりオーバーライドされているため、SampleChild#say() が呼び出されてしまう。
こういう動作になることは、親クラスの実装の詳細を知らないと知りようがない。
というわけで継承じゃなくてコンポジションを使いましょうということらしい。
コンポジションの詳しい例はEffective Java本編に譲るとして、要は転送クラスを利用することで好きなようにクラスを拡張できるし、元クラスの実装に影響を受けない作りにできるということかな。