Javaの抽象クラスと通常メソッドの使い分け方!初心者でもわかる基礎から実践
生徒
「Javaの抽象クラスって、どんなときに使うんですか?」
先生
「抽象クラスは、共通の機能は持たせつつも、一部の機能は子クラスで実装させたいときに使います。インターフェースとは違って、通常のメソッドも持てるんですよ。」
生徒
「通常のメソッドも一緒に書けるってことですか?どんな風に使えばいいんですか?」
先生
「じゃあ、Javaの抽象クラスに通常のメソッドを組み合わせた使い方について、順を追って解説していきましょう。」
1. Javaの抽象クラスとは?
Javaの抽象クラス(abstract class)は、クラスの設計段階で共通する処理や構造をまとめて定義し、継承するサブクラスで具体的な実装を補完するために使います。抽象クラスは、完全に抽象的である必要はなく、通常の具体的なメソッド(処理の中身があるメソッド)も一緒に定義することができます。
この「抽象メソッド」と「通常のメソッド」を併用することで、コードの再利用性を高めつつ、柔軟な設計が可能になります。
2. 抽象メソッドと通常メソッドの違い
抽象クラスには、以下の2種類のメソッドを定義できます。
- 抽象メソッド:処理内容を持たず、サブクラスでオーバーライドして具体的な処理を書く必要があるメソッド。
- 通常メソッド:処理内容を持っていて、そのままサブクラスで使えるメソッド。
抽象クラスを使う最大のメリットは、共通処理は抽象クラス内で一括管理し、個別の処理だけをサブクラスに任せるという設計ができることです。
3. 実際のコードで理解しよう
それでは、Javaの抽象クラスに通常メソッドと抽象メソッドを組み合わせた例を見てみましょう。
abstract class Animal {
// 抽象メソッド(サブクラスで実装が必要)
public abstract void makeSound();
// 通常のメソッド(そのまま使用可能)
public void sleep() {
System.out.println("スヤスヤ眠っています...");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("ワンワン!");
}
}
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("ニャーニャー!");
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
dog.makeSound(); // ワンワン!
dog.sleep(); // スヤスヤ眠っています...
Animal cat = new Cat();
cat.makeSound(); // ニャーニャー!
cat.sleep(); // スヤスヤ眠っています...
}
}
この例では、makeSound()は抽象メソッドとして定義されていて、各動物クラスで具体的に実装されています。一方sleep()は共通の処理なので、抽象クラスで定義して使い回しています。
4. 通常メソッドを活用するメリットとは?
抽象クラスで通常のメソッドを使うことで、次のようなメリットがあります。
- コードの重複を避けられる:共通の処理を一箇所にまとめることで、各クラスに同じコードを書く必要がなくなります。
- 保守性が高くなる:共通処理を変更するとき、抽象クラスのメソッドだけ修正すればすべての子クラスに反映されます。
- テンプレートパターンにも応用可能:基本の流れを抽象クラスで定義し、一部だけサブクラスで差し替える設計が可能です。
5. 通常メソッドと抽象メソッドの使い分け方
「すべての子クラスで同じ処理をさせたい」なら通常メソッド、「子クラスごとに違う処理をさせたい」なら抽象メソッドを使うのが基本です。
たとえば次のように使い分けます:
logMessage()のようなロギング処理 → 通常メソッドdraw()のような描画処理(図形によって異なる) → 抽象メソッド
6. よくあるエラーと注意点
抽象クラスや抽象メソッドを使う際には、以下のポイントに注意しましょう。
- 抽象クラスはインスタンス化できない:直接
newすることはできません。 - 抽象メソッドは中身を書いてはいけない:中括弧(
{})を使って処理を書こうとするとエラーになります。 - 抽象メソッドを1つでも持つクラスは抽象クラスにする必要がある:コンパイルエラーになるので注意。
7. インターフェースとの違いも押さえておこう
Javaでは、似たような仕組みとして「インターフェース」もありますが、抽象クラスとは以下の点が異なります。
- インターフェース:すべてのメソッドが抽象的(ただしJava 8以降は
defaultメソッドも定義可能) - 抽象クラス:抽象メソッドと通常メソッドを混在させることができる
どちらを使うか迷ったら、「共通処理をまとめたいなら抽象クラス」、「実装だけ任せたいならインターフェース」と覚えるとよいでしょう。