インタフェースと抽象クラスの使い分け


インタフェースと抽象クラスをどう使い分ける?

初心者が、インタフェースと抽象クラスがどんなものかを理解して、次に疑問に思うのは
それぞれ、どう使い分ければ良いの?
ということではないかと思います。

インタフェースは使用者のため、抽象クラスは実装者のため

  • インタフェースは呼び出す人のためにメソッドのAPIを定義する
  • 抽象クラスは子クラスを実装する人のために一部を実装する

端的に言えば、これだけです。

具体的には

ポリモーフィズムを使用して呼び出してもらいたいクラスは、インタフェースを実装しましょう。

使う側は、抽象クラス型の変数は宣言するべきではないです。
インタフェース型で変数を宣言しましょう。

AbstractFooBar = new FooBar(); // NG
IFooBar = new FooBar(); // OK

抽象クラスを仮引数の型とするメソッドも定義するべきではありません。
インタフェース型を指定しましょう。

void fooMethod(AbstractFooBar fooBar); // NG
void fooMethod(IFooBar fooBar); // OK

補足 抽象クラスでポリモーフィズムかけたい場合は?

では、抽象クラスの子クラス群に対してポリモーフィズム使いたい場合はどうするの?
という疑問が生まれそうなので。
その場合は、以下の感じで。

こうしておけば、使用者は常にIFooBarインタフェース経由で呼び出せば良いですし、
IFooBarインタフェースを実装する人は、
AbstractFooBarを拡張するか、直接IFooBarを実装するかを選べて、
皆が幸せになります。