Javaにおける抽象クラスの基本と応用

抽象クラスの基本概念

Javaプログラミングにおいて、抽象クラスはオブジェクト指向設計の中核的な要素です。abstractキーワードを使用して定義される抽象クラスは、直接インスタンス化できず、サブクラスによって実装されるべき共通の構造と振る舞いを定義します。

抽象クラスの定義と特徴

抽象クラスは抽象メソッドと具象メソッドの両方を含むことができます。抽象メソッドは宣言のみを持ち、実装はサブクラスに委ねられます。

// テンプレートとしての乗り物クラス
package com.vehicle.framework;

public abstract class Transport {
    private String identifier;
    
    public Transport(String id) {
        this.identifier = id;
    }
    
    public String getIdentifier() {
        return identifier;
    }
    
    // 抽象メソッド
    public abstract void operate();
    
    // 具象メソッド
    public void displayStatus() {
        System.out.println("ID: " + identifier + " - 準備完了");
    }
}

具象クラスによる実装

抽象クラスを継承する具象クラスは、すべての抽象メソッドを実装する必要があります。

package com.vehicle.framework;

public class Automobile extends Transport {
    private int fuelCapacity;
    
    public Automobile(String id, int fuel) {
        super(id);
        this.fuelCapacity = fuel;
    }
    
    @Override
    public void operate() {
        System.out.println(getIdentifier() + "が走行開始(燃料: " + fuelCapacity + "L)");
    }
    
    public void refuel(int amount) {
        fuelCapacity += amount;
        System.out.println("燃料補給完了: " + fuelCapacity + "L");
    }
}

階層構造の設計例

より複雑な階層構造を構築して、抽象クラスの活用方法を示します。

package com.vehicle.framework;

public abstract class Aircraft extends Transport {
    protected double altitude;
    
    public Aircraft(String id) {
        super(id);
        this.altitude = 0.0;
    }
    
    public void ascend(double meters) {
        altitude += meters;
        System.out.println(getIdentifier() + "が上昇: 高度" + altitude + "m");
    }
    
    public abstract void performMaintenance();
}

public class CommercialPlane extends Aircraft {
    private int passengerCount;
    
    public CommercialPlane(String id, int passengers) {
        super(id);
        this.passengerCount = passengers;
    }
    
    @Override
    public void operate() {
        System.out.println("便" + getIdentifier() + "が離陸(乗客: " + passengerCount + "名)");
    }
    
    @Override
    public void performMaintenance() {
        System.out.println("整備完了: 便" + getIdentifier());
    }
}

ポリモーフィズムの活用

抽象クラスを使用することで、異なるサブクラスを共通のインターフェースで扱うことができます。

package com.vehicle.system;

import com.vehicle.framework.*;

public class FleetManager {
    private Transport[] vehicles;
    
    public FleetManager(int capacity) {
        vehicles = new Transport[capacity];
    }
    
    public void addVehicle(int index, Transport vehicle) {
        if (index < vehicles.length) {
            vehicles[index] = vehicle;
        }
    }
    
    public void operateAll() {
        for (Transport vehicle : vehicles) {
            if (vehicle != null) {
                vehicle.displayStatus();
                vehicle.operate();
                System.out.println("---");
            }
        }
    }
    
    public static void main(String[] args) {
        FleetManager manager = new FleetManager(3);
        
        manager.addVehicle(0, new Automobile("CAR-001", 50));
        manager.addVehicle(1, new CommercialPlane("FL-101", 180));
        
        manager.operateAll();
    }
}

抽象クラスとインターフェースの比較

両者は似た役割を果たしますが、重要な違いがあります:

  • 抽象クラスは状態(フィールド)を持てるが、インターフェースは定数のみ
  • クラスは単一の抽象クラスしか継承できないが、複数のインターフェースを実装可能
  • 抽象クラスにはコンストラクタがあるが、インターフェースにはない
package com.vehicle.features;

interface Autonomous {
    void enableSelfDriving();
    default void calibrateSensors() {
        System.out.println("センサー較正実行中");
    }
}

abstract class ElectricVehicle extends Transport implements Autonomous {
    protected int batteryLevel;
    
    public ElectricVehicle(String id, int battery) {
        super(id);
        this.batteryLevel = battery;
    }
    
    public void charge(int percentage) {
        batteryLevel = Math.min(100, batteryLevel + percentage);
        System.out.println("充電完了: " + batteryLevel + "%");
    }
    
    @Override
    public abstract void enableSelfDriving();
}

public class SelfDrivingCar extends ElectricVehicle {
    private boolean isAutonomousActive;
    
    public SelfDrivingCar(String id, int battery) {
        super(id, battery);
        this.isAutonomousActive = false;
    }
    
    @Override
    public void operate() {
        if (isAutonomousActive) {
            System.out.println(getIdentifier() + "が自動運転モードで走行");
        } else {
            System.out.println(getIdentifier() + "が手動運転モードで走行");
        }
    }
    
    @Override
    public void enableSelfDriving() {
        isAutonomousActive = true;
        calibrateSensors();
        System.out.println("自動運転システム有効化");
    }
}

抽象クラスの設計原則

効果的な抽象クラス設計のためのガイドライン:

  • 共通の状態と振る舞いを抽象クラスに集約する
  • サブクラスで実装が必要な操作を抽象メソッドとして定義する
  • テンプレートメソッドパターンを活用してアルゴリズムの骨格を提供する
  • 適切なアクセス修飾子を使用してカプセル化を維持する
package com.vehicle.template;

public abstract class DataProcessor {
    
    // テンプレートメソッド
    public final void processWorkflow() {
        validateInput();
        transformData();
        storeResult();
        generateReport();
    }
    
    protected abstract void validateInput();
    protected abstract void transformData();
    protected abstract void storeResult();
    
    // フックメソッド
    protected void generateReport() {
        System.out.println("標準レポート生成完了");
    }
    
    // 共通ユーティリティ
    protected void logOperation(String operation) {
        System.out.println("操作ログ: " + operation);
    }
}

抽象クラスはJavaのオブジェクト指向プログラミングにおいて強力なツールです。適切に使用することで、コードの再利用性、拡張性、保守性を大幅に向上させることができます。

タグ: Java 抽象クラス オブジェクト指向 ポリモーフィズム デザインパターン

7月24日 18:02 投稿