テクノロジー 開発 非公開: 抽象クラス vs. Java のインターフェース: 例を示した説明

抽象クラス vs. Java のインターフェース: 例を示した説明

抽象クラスと抽象インターフェイスは、Java の抽象化に使用されます。オブジェクト指向プログラミングにおける抽象化とは、実装の詳細をエンド ユーザーから隠すことを指します。

抽象化すると、機能が何であるかを知ることができますが、それがどのように実装されたかはわかりません。

それぞれを見て、なぜそれらが使用されるのかを理解してみましょう。

抽象クラス vs. Java のインターフェース: 例を示した説明
抽象クラス vs. Java のインターフェース: 例を示した説明

抽象クラス

オブジェクトとしてインスタンス化できず、その中に抽象メソッドがある場合とない場合があるクラスを、Java では抽象クラスと呼びます。抽象メソッドは、宣言時に実装本体を持たないメソッドです。

抽象クラス GraphicObject の例 – Oracle
抽象クラスの例
抽象クラスの例

class キーワードの前に abstract キーワードを指定することで、抽象クラスを作成できます。

 abstract class abstractClass {
    void run() {
        System.out.println("ran");
    }
}

抽象クラスは他のクラスによって拡張できます。つまり、サブクラス化することもできます。

 abstract class AbstractClass {
    void run() {
        System.out.println("ran");
    }
}

class ExtendingAbstractClass extends AbstractClass {
    void newMethod() {
        System.out.println("new");
    }

    @Override
    void run() {
        System.out.println("override");
    }
}

抽象クラスは、特定の抽象クラスを拡張する複数のクラス間で共通のメソッドを実装するために使用されます。また、抽象クラス内で抽象メソッドを定義できるため、同様のメソッドを持つが実装が異なるクラスにとって、抽象メソッドは非常に便利です。例を挙げてみましょう。

発進、停止、後退などの機能を備えた車を考えてみましょう。これらの機能は、すべてのタイプの車に共通です。

しかし、自動運転などの自動化機能についてはどうなのでしょうか?これらの機能の実装は、車のタイプによって異なる場合があります。それに関連するオブジェクト指向プログラムを作成する方法を見てみましょう。

まず、さまざまな車種の複数のクラスによって拡張される Car クラスを作成します。

 abstract class Car {
    void start() {
        // implementation
        System.out.println("runs car");
    }

    void stop() {
        // implementation
        System.out.println("engine stops");
    }

    void reverse() {
        // implementation
        System.out.println("reverse mode enabled");
    }

    abstract void selfDrive();
}

start() stop() 、および reverse() メソッドは、すべての車に共通のメソッドです。したがって、それらの実装は Car クラス自体の内部ですでに定義されています。ただし、特定の種類の車では、自動運転モードの実装が異なる場合があります。したがって、 selfDrive() 抽象メソッドとして定義し、さまざまなタイプの車のさまざまなクラスでさまざまな方法で実装できます。

 class CarTypeA extends Car {
    @Override
    void start() {
        super.start();
    }

    @Override
    void stop() {
        super.stop();
    }

    @Override
    void reverse() {
        super.reverse();
    }

    void selfDrive() {
        // custom implementation
        System.out.println("Type A self driving mode enabled");
    }
}
 class CarTypeB extends Car {
    // ...all similar methods

    void selfDrive() {
        // custom implementation
        // different implementation than CarTypeB
        System.out.println("Type B self driving mode enabled");
    }
}

サブクラスが抽象クラスで定義されているすべての抽象メソッドを実装していない場合は、それ自体を抽象クラスとして宣言する必要があることに注意することが重要です。

抽象クラス vs. Java のインターフェース: 例を示した説明
抽象クラス vs. Java のインターフェース: 例を示した説明

インターフェース

インターフェイスは、どのメソッドを実装する必要があるかをクラスに伝える方法です。たとえば、自動車の例を考えてみると、自動車にはいくつかの基本的な機能があります。開始、移動、停止が可能です。これらの機能は全車共通です。

したがって、クラスに自動車のインターフェイスを実装する場合、自動車が適切かつ安全に機能するためには、すべてのメソッドを実装する必要があります。

抽象クラスと同様に、インターフェイスのオブジェクトをインスタンス化したり作成したりすることはできません。これは、抽象メソッド、つまり実装本体を持たないメソッドのみを含むため、完全な抽象クラスと考えることができます。

interface キーワードを使用してインターフェイスを作成できます。

 interface CAR {
    void start();
    void stop();
    void move();
}

クラスを定義するときに、 implements キーワードを使用してインターフェイスを実装します。

 class CarTypeB implements CAR {
    public void start() {
        System.out.println("started");
    }

    public void stop() {
        System.out.println("stopped");
    }

    public void move() {
        System.out.println("running");
    }
}
抽象クラス vs. Java のインターフェース: 例を示した説明
抽象クラス vs. Java のインターフェース: 例を示した説明

類似性

抽象クラスとインターフェイスに共通するのは、オブジェクトとしてインスタンス化されないことです。

抽象クラス vs. Java のインターフェース: 例を示した説明
抽象クラス vs. Java のインターフェース: 例を示した説明

違い

抽象クラス インターフェース
継承と実装 1 つのクラスで継承できる抽象クラスは 1 つだけです。 複数のインターフェイスを 1 つのクラスで実装できます。
変数の型 最終変数、非最終変数、静的変数、および非静的変数を含めることができます。 静的変数と最終変数のみを持つことができます。
メソッドの種類 抽象メソッドと非抽象メソッドの両方を含めることができます。 抽象メソッドのみを含めることができますが、静的メソッドは例外です。
アクセス修飾子 抽象クラスにはアクセス修飾子を含めることができます。 インターフェイスで定義されたメソッド シグネチャは、デフォルトでパブリックです。インターフェイスにはアクセス修飾子がありません。
コンストラクターとデストラクター コンストラクターとデストラクターを宣言できます。 コンストラクターやデストラクターを宣言することはできません。
スピード 速い 遅い
抽象クラスとインターフェースの違い

抽象クラスとインターフェイスをいつ使用するか?

次の場合に抽象クラスを使用します。

  • 複数のクラス間でいくつかの共通のメソッドとフィールドを共有したいと考えています。
  • non-static フィールドと non-final フィールドをバインドされているオブジェクトの状態を変更するために宣言します。

次の場合にインターフェイスを使用できます。

  • インターフェイスを実装するクラスの動作を定義したいと考えていますが、その実装方法は気にしていません。
  • クラスが適切に機能するすべてのメソッドを実装していることを確認したいとします。

最後の言葉

インターフェイスは、実際の実装を気にせずに機能を実装するための構造を提供できるため、主に API の作成に使用されます。

抽象クラスは通常、複数のクラス間で共通の抽象メソッドと非抽象メソッドを共有するために使用され、抽象クラスを拡張してコードをより再利用しやすくします。

これらの Java のオンライン コースを利用して、Java についてさらに詳しく学びましょう。 Java に関する面接の準備をしていますか?オブジェクト指向プログラミングに関する面接の質問をいくつか紹介します。

「抽象クラス vs. Java のインターフェース: 例を示した説明」についてわかりやすく解説!絶対に観るべきベスト2動画

【Java入門#20】インタフェース
【Java入門#19】抽象クラス(abstract)

抽象クラスと抽象インターフェイスは、Java の抽象化に使用されます。オブジェクト指向プログラミングにおける抽象化とは、実装の詳細をエンド ユーザーから隠すことを指します。

抽象化すると、機能が何であるかを知ることができますが、それがどのように実装されたかはわかりません。

それぞれを見て、なぜそれらが使用されるのかを理解してみましょう。

抽象クラス vs. Java のインターフェース: 例を示した説明
抽象クラス vs. Java のインターフェース: 例を示した説明

抽象クラス

オブジェクトとしてインスタンス化できず、その中に抽象メソッドがある場合とない場合があるクラスを、Java では抽象クラスと呼びます。抽象メソッドは、宣言時に実装本体を持たないメソッドです。

抽象クラス GraphicObject の例 – Oracle
抽象クラスの例
抽象クラスの例

class キーワードの前に abstract キーワードを指定することで、抽象クラスを作成できます。

 abstract class abstractClass {
    void run() {
        System.out.println("ran");
    }
}

抽象クラスは他のクラスによって拡張できます。つまり、サブクラス化することもできます。

 abstract class AbstractClass {
    void run() {
        System.out.println("ran");
    }
}

class ExtendingAbstractClass extends AbstractClass {
    void newMethod() {
        System.out.println("new");
    }

    @Override
    void run() {
        System.out.println("override");
    }
}

抽象クラスは、特定の抽象クラスを拡張する複数のクラス間で共通のメソッドを実装するために使用されます。また、抽象クラス内で抽象メソッドを定義できるため、同様のメソッドを持つが実装が異なるクラスにとって、抽象メソッドは非常に便利です。例を挙げてみましょう。

発進、停止、後退などの機能を備えた車を考えてみましょう。これらの機能は、すべてのタイプの車に共通です。

しかし、自動運転などの自動化機能についてはどうなのでしょうか?これらの機能の実装は、車のタイプによって異なる場合があります。それに関連するオブジェクト指向プログラムを作成する方法を見てみましょう。

まず、さまざまな車種の複数のクラスによって拡張される Car クラスを作成します。

 abstract class Car {
    void start() {
        // implementation
        System.out.println("runs car");
    }

    void stop() {
        // implementation
        System.out.println("engine stops");
    }

    void reverse() {
        // implementation
        System.out.println("reverse mode enabled");
    }

    abstract void selfDrive();
}

start() stop() 、および reverse() メソッドは、すべての車に共通のメソッドです。したがって、それらの実装は Car クラス自体の内部ですでに定義されています。ただし、特定の種類の車では、自動運転モードの実装が異なる場合があります。したがって、 selfDrive() 抽象メソッドとして定義し、さまざまなタイプの車のさまざまなクラスでさまざまな方法で実装できます。

 class CarTypeA extends Car {
    @Override
    void start() {
        super.start();
    }

    @Override
    void stop() {
        super.stop();
    }

    @Override
    void reverse() {
        super.reverse();
    }

    void selfDrive() {
        // custom implementation
        System.out.println("Type A self driving mode enabled");
    }
}
 class CarTypeB extends Car {
    // ...all similar methods

    void selfDrive() {
        // custom implementation
        // different implementation than CarTypeB
        System.out.println("Type B self driving mode enabled");
    }
}

サブクラスが抽象クラスで定義されているすべての抽象メソッドを実装していない場合は、それ自体を抽象クラスとして宣言する必要があることに注意することが重要です。

抽象クラス vs. Java のインターフェース: 例を示した説明
抽象クラス vs. Java のインターフェース: 例を示した説明

インターフェース

インターフェイスは、どのメソッドを実装する必要があるかをクラスに伝える方法です。たとえば、自動車の例を考えてみると、自動車にはいくつかの基本的な機能があります。開始、移動、停止が可能です。これらの機能は全車共通です。

したがって、クラスに自動車のインターフェイスを実装する場合、自動車が適切かつ安全に機能するためには、すべてのメソッドを実装する必要があります。

抽象クラスと同様に、インターフェイスのオブジェクトをインスタンス化したり作成したりすることはできません。これは、抽象メソッド、つまり実装本体を持たないメソッドのみを含むため、完全な抽象クラスと考えることができます。

interface キーワードを使用してインターフェイスを作成できます。

 interface CAR {
    void start();
    void stop();
    void move();
}

クラスを定義するときに、 implements キーワードを使用してインターフェイスを実装します。

 class CarTypeB implements CAR {
    public void start() {
        System.out.println("started");
    }

    public void stop() {
        System.out.println("stopped");
    }

    public void move() {
        System.out.println("running");
    }
}
抽象クラス vs. Java のインターフェース: 例を示した説明
抽象クラス vs. Java のインターフェース: 例を示した説明

類似性

抽象クラスとインターフェイスに共通するのは、オブジェクトとしてインスタンス化されないことです。

抽象クラス vs. Java のインターフェース: 例を示した説明
抽象クラス vs. Java のインターフェース: 例を示した説明

違い

抽象クラス インターフェース
継承と実装 1 つのクラスで継承できる抽象クラスは 1 つだけです。 複数のインターフェイスを 1 つのクラスで実装できます。
変数の型 最終変数、非最終変数、静的変数、および非静的変数を含めることができます。 静的変数と最終変数のみを持つことができます。
メソッドの種類 抽象メソッドと非抽象メソッドの両方を含めることができます。 抽象メソッドのみを含めることができますが、静的メソッドは例外です。
アクセス修飾子 抽象クラスにはアクセス修飾子を含めることができます。 インターフェイスで定義されたメソッド シグネチャは、デフォルトでパブリックです。インターフェイスにはアクセス修飾子がありません。
コンストラクターとデストラクター コンストラクターとデストラクターを宣言できます。 コンストラクターやデストラクターを宣言することはできません。
スピード 速い 遅い
抽象クラスとインターフェースの違い

抽象クラスとインターフェイスをいつ使用するか?

次の場合に抽象クラスを使用します。

  • 複数のクラス間でいくつかの共通のメソッドとフィールドを共有したいと考えています。
  • non-static フィールドと non-final フィールドをバインドされているオブジェクトの状態を変更するために宣言します。

次の場合にインターフェイスを使用できます。

  • インターフェイスを実装するクラスの動作を定義したいと考えていますが、その実装方法は気にしていません。
  • クラスが適切に機能するすべてのメソッドを実装していることを確認したいとします。

最後の言葉

インターフェイスは、実際の実装を気にせずに機能を実装するための構造を提供できるため、主に API の作成に使用されます。

抽象クラスは通常、複数のクラス間で共通の抽象メソッドと非抽象メソッドを共有するために使用され、抽象クラスを拡張してコードをより再利用しやすくします。

これらの Java のオンライン コースを利用して、Java についてさらに詳しく学びましょう。 Java に関する面接の準備をしていますか?オブジェクト指向プログラミングに関する面接の質問をいくつか紹介します。

「抽象クラス vs. Java のインターフェース: 例を示した説明」についてわかりやすく解説!絶対に観るべきベスト2動画

【Java入門#20】インタフェース
【Java入門#19】抽象クラス(abstract)