Effective Java 18章 抽象クラスよりインタフェースを選ぶ

More than 1 year has passed since last update.

Effective Javaの18章「抽象クラスよりインタフェースを選ぶ」を読んだので軽くまとめます。

インターフェースと抽象クラスの違い

インターフェースと抽象クラスは、複数の実装を許す為の仕組みの1つである。
両者の違いは、抽象クラスはメソッドの実装を持てるのに対してインターフェースは持てないことである。
インターフェースはクラス階層のどこに属していても実装できる。抽象クラスもどの階層においても実装できるが、Javaでは単一継承しか許されていない為、型定義をする為に抽象クラスを使用するのは非常に不便になる。
例えば、2つの異なるクラスA, Bに対して、抽象クラスCを実装させたいとする。その場合、AとBの祖先がCになるように実装しなければならない。ここで問題になるのは、AとBに関係ないクラスまでCを実装する必要が出て来てしまうことである。

ミックスイン

複数のインターフェースを混ぜ合わせて振る舞わせることをミックスインと呼ぶ。たとえば、以下のようなSingerインターフェースとSongwriterインターフェースがあるとする。

Singer.java
public interface Singer {
    AudioClip sing(Song s);
}
Songwriter.java
public interface Songwriter {
    Song compose(boolean hit);
}

これらをミックスインし、以下のようなSingerSongwriterインターフェースを定義できる。

SingerSongwriter.java
public interface SingerSongwriter extends Singer, Songwriter {
    AudioClip strum();
    void actSensitive();
}

これは抽象クラスでは実現出来ない。なぜなら、Javaではクラスは2つ以上の親を持つこと(多重継承)ができないから。無理に継承を使って実装しようとすると、組み合わせ爆発(combinational explosion)が起こり、クラス階層が膨れ上がる。

骨格実装

Javaではインターフェースに実装を含むことは許されていないが、それ単体で提供しても実装者の負担になるだけである。そこで、インターフェースと一緒に骨格実装クラスを提供することでその問題を解決する。
骨格実装クラスはAbstractInterfaceと呼ばれ、Javaの主要なCollection Frameworkではそれが提供されている。例えば、 List インターフェースに対しては AbstractList が提供されている。
ほとんどの場合、骨格実装を拡張してインターフェースを実装することを選択すべきである。

骨格実装を作る場合、それが継承して使われることを想定して実装すべきである。ドキュメントと設計の指針に正しく従って設計を行う。

インターフェースの変更は困難

一度リリースされたpublicなインターフェースに対し、後から変更を加えることは非常に難しい。
このような問題を回避する為、正式リリース前にできるだけ多くのプログラマにこのインターフェースを使って実装してもらい、欠陥を早期に発見できるようにすると良い。インターフェースは最初から正しい設計をする必要がある。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.