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

抽象クラスとインターフェースの違いは、人気のある面接の質問の一つです。抽象クラスとインターフェースは、Javaプログラミング言語の中核をなす要素です。インターフェースを選ぶか、抽象クラスを選ぶかは、すべての設計者が直面する設計上の決定です。私の前の記事では、Javaのインターフェース抽象クラスについてできる限り詳細を提供しました。この投稿では、抽象クラスとインターフェースの違い、およびいつインターフェースを使い、いつ抽象クラスを使うべきかについて学びます。

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

  1. abstractキーワードは抽象クラスを作成するために使用され、メソッドとも使用できますが、interfaceキーワードはインターフェースを作成するために使用され、メソッドとは使用できません。
  2. サブクラスは抽象クラスを拡張するためにextendsキーワードを使用し、抽象クラス内で宣言されたすべてのメソッドの実装を提供する必要があります(ただし、サブクラス自体が抽象クラスである場合を除く)。一方、サブクラスはインターフェースを実装するためにimplementsキーワードを使用し、インターフェースで宣言されたすべてのメソッドの実装を提供する必要があります。
  3. 抽象クラスは実装されたメソッドを持つことができますが、インターフェースは絶対的な抽象化を提供し、メソッドの実装を持つことはできません。Java 8以降では、インターフェースにデフォルトおよび静的メソッドを作成でき、それにはメソッドの実装が含まれます。
  4. 抽象クラスはコンストラクタを持つことができますが、インターフェースはコンストラクタを持つことはできません。
  5. 抽象クラスは通常のJavaクラスのすべての機能を持っていますが、インスタンス化することはできません。クラスを抽象にするには、abstractキーワードを使用できますが、インターフェースは完全に異なるタイプで、public static finalの定数とメソッド宣言のみを持つことができます。
  6. 抽象クラスのメソッドはpublic、private、protected、staticなどのアクセス修飾子を持つことができますが、インターフェースのメソッドは暗黙的にpublicおよびabstractであり、他のアクセス修飾子を使用できません。
  7. A subclass can extend only one abstract class but it can implement multiple interfaces.
  8. 抽象クラスは他のクラスを拡張し、インターフェースを実装できますが、インターフェースは他のインターフェースのみを拡張できます。
  9. 抽象クラスはmain()メソッドを持っていれば実行できますが、インターフェースは実行できません。なぜなら、インターフェースにはmainメソッドの実装ができないからです。
  10. インターフェースはサブクラスのための契約を定義するために使用されますが、抽象クラスも契約を定義でき、サブクラスが使用するための他のメソッドの実装を提供できます。

これでインターフェースと抽象クラスの違いについては以上です。次に、いつインターフェースを使用し、逆に抽象クラスを使用すべきかを知ることができます。

インターフェースまたは抽象クラス

サブクラスに対する契約を提供するためにインターフェースまたは抽象クラスを選択するかどうかは、設計上の決定であり、多くの要因に依存します。インターフェースが最良の選択肢である場合と、抽象クラスを使用できる場合を見てみましょう。

  1. Javaは複数のクラスレベルの継承をサポートしていないため、すべてのクラスは1つのスーパークラスのみを拡張できます。ただし、クラスは複数のインターフェースを実装できます。そのため、ほとんどの場合、インターフェースはクラス階層と契約の基盤を提供するのに適した選択肢です。また、インターフェースを使用してコーディングすることは、Javaでのコーディングのベストプラクティスの一つです。
  2. 契約に多くのメソッドがある場合、抽象クラスの方が便利です。なぜなら、すべてのサブクラスに共通のいくつかのメソッドのデフォルトの実装を提供できるからです。また、サブクラスが特定のメソッドを実装する必要がない場合、実装を省略できますが、インターフェースの場合は、サブクラスがそのメソッドの実装を提供する必要があります。それがどのように使用されるかに関係なく、実装が空のブロックであってもです。
  3. 基本契約が変更され続ける場合、インターフェースは問題を引き起こす可能性があります。なぜなら、インターフェースに追加のメソッドを宣言できないため、すべての実装クラスを変更する必要があるからです。抽象クラスでは、デフォルトの実装を提供し、新しいメソッドを実際に使用する実装クラスのみを変更できます。

抽象クラスとインターフェースの両方を使用する

インターフェースと抽象クラスを併用するのがシステム設計の最良の方法です。例えば、JDKではjava.util.Listが多くのメソッドを含むインターフェースであり、そのためにjava.util.AbstractListという抽象クラスが提供されています。これはListインターフェースのすべてのメソッドの骨組みの実装を提供し、そのために任意のサブクラスがこのクラスを拡張し、必要なメソッドのみを実装できるようにします。常に基本となるインターフェースから始めて、すべてのサブクラスが実装すべきメソッドを定義し、特定のサブクラスのみが実装すべきメソッドがある場合は、基本インターフェースを拡張してそのメソッドを持つ新しいインターフェースを作成します。サブクラスは、要件に応じて基本インターフェースまたは子インターフェースのどちらを実装するかを選択するオプションがあります。メソッドの数が多くなると、子インターフェースを実装する骨格の抽象クラスを提供し、サブクラスがインターフェースと抽象クラスの間を選択できる柔軟性を提供するのも悪くありません。

Java 8のインターフェースの変更

Java 8 以降、インターフェース内でメソッドの実装が可能です。デフォルトおよび静的メソッドをインターフェース内に作成し、それに対する実装を提供できます。これにより、抽象クラスとインターフェースの間の差が埋まり、新しいメソッドに対するデフォルトの実装を提供することで、インターフェースが進化することができるようになりました。詳細については、Java 8 インターフェース デフォルト 静的メソッドをチェックしてください。

Source:
https://www.digitalocean.com/community/tutorials/difference-between-abstract-class-and-interface-in-java