ProgrammingJava開発者

Javaにおける抽象クラスとインターフェースの主な違い、およびそれぞれを使用するべきシナリオについて説明してください。

Hintsage AIアシスタントで面接を突破

回答

抽象クラスは、抽象メソッドと具体的なメソッド(実装を持つ)および状態(データフィールド)を含むことができます。クラスは1つの抽象クラスからのみ継承できます。抽象クラスは、継承の階層に対して論理や状態の一部を一般化する必要がある場合に使用します。

インターフェースは、メソッドのシグネチャのみを定義します(Java 8以前)。Java 8からは、デフォルトの実装を持つメソッド(default)や静的メソッドを含むことができますが、状態は持ちません。1つのクラスは複数のインターフェースを実装できます。インターフェースは、継承の階層に依存しない振る舞いのセットを指定するために使用します。

例:

abstract class Animal { String name; public Animal(String name) { this.name = name; } abstract void makeSound(); } interface Movable { void move(); } class Dog extends Animal implements Movable { public Dog(String name) { super(name); } void makeSound() { System.out.println("Woof!"); } public void move() { System.out.println("Runs"); } }

ひっかけ問題

抽象メソッドのみを持つ抽象クラスと、Java 8以前のインターフェースの違いは何ですか?互換的に使用できますか?

回答: いいえ、必ずしもそうではありません。インターフェースは状態(インスタンスフィールド)を持つことができず、複数の実装をサポートしますが、抽象クラスの継承は単一です。また、インターフェースのメソッドのシグネチャは常にpublicです。


テーマの微妙さを知らないことによる実際のエラーの例


ストーリー

プロジェクトで、異なる階層に属するが振る舞いが似た多数のインターフェースを実装する必要がありました。開発者は抽象クラスの使用を選択したため、複数の継承が不可能になりました。その後、これは大規模なリファクタリングとコードの重複を招きました。


ストーリー

大規模なREST APIプロジェクトで、通常のクラスのように変更可能な値を期待してフィールド(定数)を持つインターフェースが作成されました。その結果、これらのフィールドを変更しようとすると、Silent Failureが発生し、値は変更されず、バグの発見が長引きました。


ストーリー

Java 8への移行中に、開発者がインターフェースに実装を持つメソッドを追加しましたが、一部のクラスが同名のメソッドを抽象クラスを介して継承していることを考慮するのを忘れました。これにより、メソッドの競合と結果の予期しない動作が発生しました。