前回はswitch文を使った電卓プログラムを作りました。
今回は、継承をさらに発展させた「インターフェース」と「抽象クラス」について解説します。 これらを使うことで、クラスの設計をより明確にし、実装漏れを防ぎながら柔軟なプログラムを作れるようになります。
抽象クラスの基本
以前学んだ継承では、Student や Teacher が Person クラスを継承していました。ここで、もし Person クラス自体は直接インスタンス化させたくない、つまり「Person という曖昧な存在ではなく、必ず Student や Teacher として使ってほしい」という場合があります。
こうしたときに使うのが「抽象クラス」です。抽象クラスは abstract というキーワードをつけて定義し、new で直接インスタンスを作ることができません。
public abstract class クラス名 {
abstract 戻り値の型 メソッド名(引数);
}
abstract がついたメソッド(抽象メソッド)は、中身の処理を書かず、子クラス側で必ずオーバーライドして実装する必要があります。
インターフェースの基本
「インターフェース」は抽象クラスをさらに発展させたもので、「このクラスはこういうメソッドを持っているべきだ」という約束事(仕様)だけを定義します。
public interface インターフェース名 {
戻り値の型 メソッド名(引数);
}
クラスがインターフェースを使う場合は implements というキーワードを使います。
public class クラス名 implements インターフェース名 {
// インターフェースで定義されたメソッドを必ず実装する
}
インターフェースで定義されたメソッドは、それを実装するクラスの中で必ずオーバーライドして中身を書かなければなりません。書き忘れるとコンパイルエラーになるため、実装漏れを防ぐことができます。
サンプルコード(インターフェースの実装)
ファイル作成
「Java03」フォルダに Animal.java、Dog.java、Cat.java、InterfaceTest.java という名前でファイルを作成します

コード入力
Animal.java に以下のコードを入力します。
public interface Animal {
void makeSound();
}

Dog.java に以下のコードを入力します。
public class Dog implements Animal {
@Override
public void makeSound() {
System.out.println("ワンワン!");
}
}

Cat.java に以下のコードを入力します。
public class Cat implements Animal {
@Override
public void makeSound() {
System.out.println("ニャー!");
}
}

InterfaceTest.java に以下のコードを入力します。
public class InterfaceTest {
public static void main(String[] args) {
Animal[] animals = new Animal[2];
animals[0] = new Dog();
animals[1] = new Cat();
for (int i = 0; i < animals.length; i++) {
animals[i].makeSound();
}
}
}

コンパイル
javac Animal.java Dog.java Cat.java InterfaceTest.java

実行
java InterfaceTest
実行結果は次のようになります。
ワンワン!
ニャー!

コードの解説
Animal インターフェースは makeSound() というメソッドの「約束事」だけを定義しています。中身の処理は書かれていません。
Dog クラスと Cat クラスは、どちらも implements Animal とすることで、「Animal の約束を守る」ことを宣言しています。そのため、それぞれのクラスで makeSound() を @Override で実装する必要があります。もし実装を忘れると、コンパイル時にエラーが出るため、実装漏れにすぐ気づくことができます。
Animal[] animals = new Animal[2]; の部分は、以前学んだポリモーフィズムと同じ考え方です。Animal インターフェースを実装している Dog と Cat は、どちらも Animal 型の配列に入れることができます。animals[i].makeSound(); を呼び出すと、実際のインスタンスが Dog であれば「ワンワン!」、Cat であれば「ニャー!」が表示されます。
抽象クラスとインターフェースは似ていますが、抽象クラスは「共通のフィールドや、一部だけ実装済みのメソッドを持たせたい」場合に向いており、インターフェースは「実装は持たず、メソッドの約束事だけを決めたい」場合に向いています。また、Javaのクラスは1つの親クラスしか継承できませんが、インターフェースは複数同時に実装することができるという違いもあります。
まとめ
抽象クラスとインターフェースは、どちらも「クラスが持つべきメソッドの仕様」を決めるための仕組みです。抽象クラスは abstract を使い、一部の実装を持たせつつ継承させたい場合に、インターフェースは implements を使い、純粋に約束事だけを決めて複数のクラスに共通の振る舞いを持たせたい場合に使います。これらを使うことで、大きなプログラムでも設計がぶれにくくなり、チームで開発する際にも実装漏れを防ぎやすくなります。これでオブジェクト指向の主要な概念は一通り学んだことになります。
2026/06/22(月) ぱんまる


コメント