Javaの抽象クラス徹底解説!基本から応用まで初心者向けガイド
生徒
「抽象クラスって何ですか?インタフェースとの違いも教えてください!」
先生
「抽象クラスは、クラスとインタフェースの性質を合わせ持ったものです。共通する実装を持たせつつ、具体的な処理はサブクラスに任せることができます。一緒に学んでいきましょう!」
1. 抽象クラスとは?
抽象クラスは、Javaでオブジェクト指向プログラミングを行う際に重要な役割を果たすクラスです。abstractキーワードを使って定義され、以下の特徴を持ちます:
- 抽象クラスはインスタンス化できません。
- 具象メソッド(具体的な実装を持つメソッド)と抽象メソッド(実装を持たないメソッド)の両方を定義できます。
- 抽象クラスは、サブクラスに共通の動作を提供するために使用されます。
次の例を見てみましょう:
public abstract class Animal {
public abstract void makeSound(); // 抽象メソッド
public void sleep() { // 具象メソッド
System.out.println("Sleeping...");
}
}
このコードでは、Animalクラスに抽象メソッドmakeSoundと具象メソッドsleepが定義されています。
2. 抽象クラスの継承と実装
抽象クラスを継承するクラスは、その抽象メソッドを実装する必要があります。以下に例を示します:
public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Woof Woof!");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.makeSound(); // 出力: Woof Woof!
dog.sleep(); // 出力: Sleeping...
}
}
このコードでは、DogクラスがAnimalクラスを継承し、makeSoundメソッドを実装しています。
3. 抽象クラスとインタフェースの違い
抽象クラスとインタフェースは似ていますが、以下の違いがあります:
- 抽象クラスは具象メソッドとフィールドを持つことができますが、インタフェースは基本的に定数フィールドと抽象メソッドのみを持ちます(Java 8以降、一部例外あり)。
- クラスは1つの抽象クラスしか継承できませんが、複数のインタフェースを実現できます。
- 抽象クラスは共通の動作を提供し、インタフェースは「型」としての役割を強調します。
4. 試験対策ポイント
- 抽象クラスはインスタンス化できません。
- 抽象メソッドは、具象クラスが必ず実装しなければなりません。
- 抽象クラスを継承した抽象クラスも作成できます。
- 公開フィールドにはサブクラスから自由にアクセスできます。
5. 抽象クラスにコンストラクタは作れる?
抽象クラスはインスタンス化できませんが、コンストラクタを定義することは可能です。 抽象クラスのコンストラクタは、サブクラスのオブジェクトが生成されるときに呼び出されます。
次のコードを見てみましょう:
public abstract class Animal {
public Animal() {
System.out.println("Animal constructor");
}
public abstract void makeSound();
}
public class Dog extends Animal {
public Dog() {
System.out.println("Dog constructor");
}
@Override
public void makeSound() {
System.out.println("Woof!");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
}
}
この場合、Dogのオブジェクトが生成されると、まずAnimalのコンストラクタが呼び出され、その後にDogのコンストラクタが実行されます。
6. 抽象クラスをさらに抽象クラスで継承する
抽象クラスは、別の抽象クラスに継承させることもできます。 この場合、抽象メソッドを実装しなくても問題ありません。最終的な具象クラスが実装すればよいからです。
次の例を見てみましょう:
public abstract class Animal {
public abstract void makeSound();
}
public abstract class Mammal extends Animal {
public void breathe() {
System.out.println("Breathing...");
}
}
public class Dog extends Mammal {
@Override
public void makeSound() {
System.out.println("Woof!");
}
}
このように、抽象クラス同士で継承関係を作ることで、 共通の機能を段階的に整理することができます。
7. 抽象クラスを使う設計パターン
抽象クラスは、複数のクラスで共通する処理をまとめるときによく使われます。 特に「テンプレートメソッドパターン」と呼ばれる設計でよく利用されます。
次の例を見てみましょう:
public abstract class Game {
public void play() {
start();
perform();
end();
}
abstract void start();
abstract void perform();
abstract void end();
}
public class Soccer extends Game {
void start() {
System.out.println("Soccer game started");
}
void perform() {
System.out.println("Playing soccer...");
}
void end() {
System.out.println("Soccer game finished");
}
}
この例では、ゲームの流れ(playメソッド)は抽象クラスで定義し、
実際の処理はサブクラスで実装しています。
このように抽象クラスを使うことで、プログラムの構造を整理しやすくなります。
まとめ
今回は、Javaの抽象クラスについて基本から応用まで解説しました。抽象クラスは、インスタンス化できないため継承専用ですが、共通の機能をサブクラスに提供する重要な役割を持っています。また、抽象メソッドを使用することで、サブクラスに具体的な実装を強制できます。 抽象クラスとインタフェースの違いについても学びましたが、それぞれの特徴を理解して使い分けることが重要です。
以下は、抽象クラスを活用した簡単なサンプルコードです:
public abstract class Vehicle {
public abstract void start();
public void stop() {
System.out.println("The vehicle stops.");
}
}
public class Car extends Vehicle {
@Override
public void start() {
System.out.println("The car starts with a key.");
}
}
public class Main {
public static void main(String[] args) {
Vehicle myCar = new Car();
myCar.start(); // 出力: The car starts with a key.
myCar.stop(); // 出力: The vehicle stops.
}
}
このコードでは、Vehicleクラスを抽象クラスとして定義し、サブクラスCarが抽象メソッドstartを実装しています。
生徒
「抽象クラスって、具体的な実装と抽象的なメソッドを混ぜられるのが便利ですね!」
先生
「その通りです。継承関係を設計するときに、抽象クラスを使うと共通の動作を簡単にまとめられますよ。」
生徒
「インタフェースとの違いもわかりました。複数のインタフェースを実現する場合と、抽象クラスを1つだけ継承する場合の使い分けが重要なんですね。」
先生
「その通り!抽象クラスとインタフェースを適切に使い分けて、効率的なコードを書いていきましょう。」