Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。

abstract

このページではabstract修飾子について説明します。

概要

abstractはクラス・メソッド宣言時に付与し、クラス・メソッドを抽象クラス(abstractクラス)・抽象メソッド(abstractメソッド)として宣言します。抽象クラスはそのクラス自身のインスタンスを生成することはできません。通常抽象クラスは実装のないいくつかの抽象メソッドを持っています。抽象クラスをサブクラスで継承し、そのサブクラス内で抽象クラスで実装されていない抽象メソッドを実装(オーバーライド)しインスタンスを生成します。

抽象クラス_1

抽象クラス、抽象メソッドは、ある事象の共通となるフレーム部分を定義し、具体的な処理は継承したサブクラスで実装したい場合に使用します。例えば、「自動車」クラスを構成する要素として「エンジン」、「ブレーキ」、「ハンドル」があります。「エンジン」、「ブレーキ」、「ハンドル」は車種によって異なるので「自動車」クラスの中では定義しません。

その場合は「自動車」クラスを抽象クラスとして宣言し、「エンジン」、「ブレーキ」、「ハンドル」を抽象メソッドとして宣言し、具体的な処理は継承したサブクラスの中で定義します。

抽象クラス_2

また、具体的な処理を子クラスとしても定義せず、さらに細分化した孫クラスで定義したい場合があります。例えば、「自動車」クラスのサブクラスとして、「ファミリーカー」クラスを宣言します。「ファミリーカー」クラスの中で「エンジン」、「ブレーキ」は共通だが、「ハンドル」はさらに細分化したい場合があります。その場合は、「エンジン」、「ブレーキ」のみ具体的な処理を記述し、「ハンドル」は抽象メソッドとして宣言し、具体的な処理はさらに継承した孫クラスで定義します。

抽象クラス_3

抽象クラスには以下のルールがあります。

  1. 抽象クラスのインスタンスを生成することはできません。
  2. 抽象クラスには抽象メソッドがあってもいいし、抽象メソッドでないメソッドがあってもいいです。しかし、抽象メソッドがあるクラスは必ず抽象クラスとして宣言する必要があります。
  3. 抽象メソッドがない、抽象クラスを宣言することもできます。ただし、かならず継承が行われ、なんらかのメソッドの変更があることを表します。
  4. 抽象クラスを継承したサブクラスで抽象メソッドを実装(オーバーライド)しない場合、そのサブクラスは抽象クラスとして宣言されます。

使用方法

抽象クラスはクラス宣言時に、abstractを付与して宣言します。

abstract class クラス名 { クラス本体 }

抽象メソッドはメソッド宣言時に、abstractを付与して宣言します。抽象メソッドは実装を持たないため宣言時、{}及び、その中の実装も記述しません。

abstract 戻り型 メソッド名(引数型 引数名);

自動車クラス(Carクラス)を抽象クラスとして宣言し、子クラスのファミリーカークラス(FamilyCarクラス)でエンジン、ブレーキメソッドを実装、孫クラスのミニバンクラス(MiniBanクラス)でハンドルメソッドを実装した例を記載します。

自動車クラス(Carクラス)

//Carクラスを抽象クラスとして宣言します。
abstract class Car{
  abstract void engine ();
  abstract void brake ();
  abstract void handle ();
}

ファミリーカークラス(FamilyCarクラス)

//抽象メソッドがあるため、抽象クラスとして宣言します。
abstract class FamilyCar extends Car{
  //エンジンメソッドをオーバーライドします。
  @Override
  void engine () {
    System.out.println("ファミリーカークラスのエンジンです。");
  }
  //ブレーキメソッドをオーバーライドします。
  @Override
  void brake () {
    System.out.println("ファミリーカークラスのブレーキです。");
  }
  //ハンドルメソッドはさらに具体的な処理を記述するため、ここでは実装しません。
  abstract void handle ();
}

ミニバンクラス(MiniBanクラス)

class MiniBan extends FamilyCar{
  //FamilyCarクラスで実装されていないハンドルメソッドをオーバーライドし、実装します。
  @Override
  void handle () {
    System.out.println("ミニバンクラスのハンドルです。");
  }
}

抽象クラスとインタフェースの違い

メソッドのヘッダーのみ宣言し、実装を継承したサブクラスに任せる(インタフェースの場合はインプリメントしたクラスに任せる)といったことを考えると抽象クラスとインタフェースは似た役割をはたします。

しかし両者には大きな違いがあります。その違いを以下に記載します。

  1. 抽象クラスには抽象メソッドと抽象メソッドでないメソッドの両方を宣言することができますが、インタフェースは抽象メソッドのみしか宣言することができません。
  2. サブクラスで継承できる抽象クラスはJavaは多重継承をサポートしていないため、1つのみです。インプリメントするインタフェースは複数インプリメントすることができます。
  3. 抽象クラスの機能を利用するためには抽象クラスを継承する必要があります。そのため、その機能は継承関係内に限られます。インタフェースはインプリメントにより利用することができます。そのため、その機能が継承関係内に限られることはありません。

14abstract