この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:7
ページ更新者:T
更新日時:2026-06-11 07:12:00

タイトル: 抽象クラス・メソッド
SEOタイトル: Java 抽象クラス・抽象メソッド完全ガイド

この記事の要点
  • abstract class はインスタンス化できないクラス。共通実装+"サブクラスで実装させたいメソッド"を持てる
  • abstract method はメソッド本体を持たない宣言だけのメソッド。サブクラスで @Override 実装が強制される
  • abstractfinal併用不可。継承できないクラスは抽象にできない
  • interface との違い: 抽象クラスは"状態 (フィールド) + コンストラクタ"を持てる。Java 8+ の interface default メソッドで境界が曖昧化
  • 現代の設計指針: Composition > Inheritance。Template Method パターンが使えるなら抽象クラス、それ以外は interface + 委譲

抽象クラスの基本

// abstract クラス: インスタンス化できない
public abstract class Animal {
    private final String name;

    // ★ 抽象クラスもコンストラクタを持てる
    protected Animal(String name) {
        this.name = name;
    }

    // 共通実装 (具象メソッド)
    public String getName() {
        return name;
    }

    // 抽象メソッド: サブクラスで実装強制
    public abstract String cry();
}

// 具象サブクラス
public class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }

    @Override
    public String cry() {
        return "ワン";
    }
}

// 使い方
Animal a = new Animal("a");  // ❌ コンパイルエラー
Animal d = new Dog("ポチ");  // ✅ サブクラス経由でインスタンス化
System.out.println(d.cry()); // ワン

abstract の制約まとめ

項目抽象クラス抽象メソッド
インスタンス化不可 (new 不可)
本体持てる (フィールド、具象メソッド、コンストラクタ)持てない ({} なし)
final 併用不可 (継承前提なので矛盾)不可 (オーバーライド前提)
private 併用OK (内部クラスなら)不可 (サブクラスから見えない)
static 併用OK (内部クラスなら)不可 (static は継承で上書き不可)
サブクラスでの実装全抽象メソッドを実装 or サブクラスも abstract に必須 (実装しないなら自身も abstract)

interface との違い

// interface: 純粋な契約 (Java 7 以前)
public interface Flyable {
    void fly();
}

// Java 8+ default メソッド導入で interface も実装を持てる
public interface Swimmable {
    default void swim() {
        System.out.println("デフォルト遊泳");
    }

    // private メソッド (Java 9+)
    private void helper() { ... }

    // static メソッド (Java 8+)
    static Swimmable empty() { return () -> {}; }
}

// 抽象クラス: 状態を持てる
public abstract class Vehicle {
    protected int speed;        // フィールド
    protected Vehicle(int s) { this.speed = s; }  // コンストラクタ
    public abstract void move();
}
項目abstract classinterface
多重継承×(1 クラスのみ)○(複数 implements 可)
フィールド○(任意の修飾子)△(public static final のみ = 定数)
コンストラクタ×
具象メソッド○(任意)○(default / static / private)
状態 (state)×(default も状態は持てない)
用途共通実装+状態を共有する継承階層能力 (can-do) の宣言

典型パターン1: Template Method

抽象クラスの最頻出パターン。"アルゴリズムの骨格"を抽象クラスに定義し、可変部分をサブクラスに任せる:

public abstract class DataProcessor {
    // 骨格 (final で上書き禁止)
    public final void process() {
        var data = load();
        var result = transform(data);
        save(result);
    }

    protected abstract List<String> load();
    protected abstract List<String> transform(List<String> data);
    protected abstract void save(List<String> data);
}

public class CsvProcessor extends DataProcessor {
    @Override protected List<String> load() {
        return Files.readAllLines(Path.of("input.csv"));
    }
    @Override protected List<String> transform(List<String> data) {
        return data.stream().map(String::toUpperCase).toList();
    }
    @Override protected void save(List<String> data) {
        Files.write(Path.of("output.csv"), data);
    }
}

new CsvProcessor().process();  // 骨格に従って実行

典型パターン2: Strategy (interface 版)

// Strategy は interface の方が自然
public interface SortStrategy<T> {
    List<T> sort(List<T> data);
}

public class QuickSort<T extends Comparable<T>> implements SortStrategy<T> {
    @Override public List<T> sort(List<T> data) { ... }
}

public class Context<T> {
    private final SortStrategy<T> strategy;
    public Context(SortStrategy<T> s) { this.strategy = s; }
    public List<T> run(List<T> data) { return strategy.sort(data); }
}

// 利用
var ctx = new Context<>(new QuickSort<Integer>());
ctx.run(List.of(3, 1, 2));

Java 17 の sealed クラス

Java 17 で sealed が導入され、"継承を許可するサブクラスを明示"できるようになりました:

public sealed abstract class Shape
    permits Circle, Square, Triangle {
    public abstract double area();
}

public final class Circle extends Shape {
    private final double r;
    public Circle(double r) { this.r = r; }
    @Override public double area() { return Math.PI * r * r; }
}

// sealed なので Circle, Square, Triangle 以外は extends 不可
// → switch のパターンマッチで網羅性が型レベルで保証される
public double describe(Shape s) {
    return switch (s) {
        case Circle c   -> c.area();
        case Square sq  -> sq.area();
        case Triangle t -> t.area();
        // default 不要 (網羅されているため)
    };
}

いつ抽象クラスを使うか

状況推奨
共通のフィールドコンストラクタを共有abstract class
Template Method (骨格固定)abstract class + final 骨格メソッド
"できる能力"の宣言 (Flyable, Comparable など)interface
多重実装が必要interface
サブクラス集合を限定したいsealed class (Java 17+)
レコード型データrecord (継承不可)

現代の設計指針

Effective Java 等で繰り返し説かれる原則: Composition > Inheritance (継承より委譲)。安易な抽象クラスはサブクラスとの密結合を生むため、可能なら interface + final class + 委譲が推奨されます。

FAQ

Q: abstract class にコンストラクタは何のため?
A: サブクラスの super(...) 呼び出しで使われます。フィールド初期化は抽象クラスで集約できます。

Q: 抽象メソッドのアクセス修飾子は?
A: public / protected / パッケージプライベートは OK。private は不可 (オーバーライドできないため)。

Q: interface だけで全部書けるなら abstract class は不要?
A: 状態 (フィールド) を共有したい・コンストラクタで不変条件を確立したい場合は abstract class が必要です。