抽象クラスとは
メソッドの名前や引数、戻り値だけを定義し、処理内容を記述しないメソッドを抽象メソッドと呼びます。そして抽象メソッドを持つことができるクラスを抽象クラスといいます。抽象クラスのオブジェクトを作成することはできず、抽象メソッドを含む抽象クラスを継承した場合、サブクラスでは抽象メソッドを必ずオーバーライドして実装する必要があります。ここではオブジェクト指向における抽象クラスの役割について解説します。
抽象クラスとは
オブジェクト指向ではクラスを継承してサブクラスを作成することができますが、スーパークラスでメソッドの名前や引数、戻り値だけを定義し、処理内容を記述しないメソッドを作ることができます。このようなメソッドを抽象メソッドと呼び、抽象メソッドを持つことができるクラスを抽象クラスといいます。
抽象クラスを定義する場合は abstract を記述します。
abstract class クラス名 {
}
抽象クラスのオブジェクトを作成することはできません。抽象クラスは継承されることを前提としたクラスです。抽象クラスのオブジェクトを作成しようとすると、コンパイルエラーとなります。
abstract class Product {
}
public class Sample {
public static void main(String[] args) {
Product f = new Product(); // 抽象クラスのオブジェクトは作成できない
}
}
抽象クラスでは抽象メソッドを持つことができます。ただし必ず抽象メソッドを定義する必要はないため、抽象メソッドが一つも含まれない抽象クラスも作成できます(この場合はオブジェクトが作成できないクラスとなります)。
abstract class Product {
abstract void showInfo(); // 抽象メソッド
}
抽象クラスは抽象メソッドだけでなく通常のクラスと同じようにフィールドや通常のメソッドを定義することができます。
abstract class Product {
private String name;
abstract void showInfo();
public void setName(String name) {
this.name = name;
}
}
抽象クラスはオブジェクトを作成できませんが、コンストラクタを持つことはできます。この場合、抽象クラスのサブクラスのオブジェクトを作成した場合に、サブクラスのコンストラクタから super() によって呼び出されます。
abstract class Product {
String name;
public Product() {
name = "未定義";
}
abstract void showInfo();
public void setName(String name) {
this.name = name;
}
}
抽象メソッド
抽象クラスでは、処理の内容を記述しないメソッドを定義することができます。このようなメソッドを抽象メソッドといいます。抽象メソッドは abstract キーワードを付けて定義します。書式は次の通りです。
abstract 戻り値の型 メソッド名(引数);
抽象メソッドは処理の内容を持たず、メソッドの宣言のみを行います。そのためメソッドの本体は記述しません。
abstract class Product {
abstract void showInfo();
}
抽象メソッドを持つクラスは必ず抽象クラスとして定義する必要があります。
抽象メソッドを持つ抽象クラスを継承した場合、サブクラスでは抽象メソッドをオーバーライドして実装する必要があります。
abstract class Product {
abstract void showInfo();
}
class Foods extends Product {
public void showInfo() {
System.out.println("食料品です");
}
}
抽象メソッドを持つ抽象クラスを継承したのに、サブクラスで抽象メソッドをオーバーライドしなかった場合は、コンパイルエラーとなります。
abstract class Product {
abstract void showInfo();
}
class Foods extends Product {
private String name;
public void setName(String name) {
this.name = name;
}
}
抽象クラスを作成する目的
抽象クラスの中に抽象メソッドを定義した場合、サブクラスでは抽象メソッドを必ずオーバーライドして実装することを義務づけることができます。その結果、各サブクラスで同じ名前や引数を持つメソッドが必ず実装されることになります。
抽象クラスでは通常のメソッドも定義できるため、各サブクラスで共通するメソッドをスーパークラスの方で定義しつつ、サブクラス側で必ず実装すべきメソッドをルールとして定義することができます。
このように抽象クラスを使用することで、共通処理をまとめながらサブクラスに実装を強制することができます。
では簡単なサンプルを作って試してみます。テキストエディタで次のように記述したあと、 Sample.java という名前で保存します。
public class Sample {
public static void main(String[] args) {
Product[] list = new Product[2];
list[0] = new Foods();
list[1] = new Gadgets();
for (Product p : list) {
p.showInfo();
}
}
}
abstract class Product {
abstract public void showInfo();
}
class Foods extends Product {
public void showInfo() {
System.out.println("食料品です");
}
}
class Gadgets extends Product {
public void showInfo() {
System.out.println("電化製品です");
}
}
コンパイルを行います。
javac -encoding UTF-8 Sample.java
その後で、次のように実行してください。
java Sample
抽象メソッド showInfo を持つ抽象クラス Product を定義し、Foods クラスと Gadgets クラスで Product クラスを継承しています。サブクラスでは抽象メソッドをオーバーライドして処理内容を実装しています。抽象クラスでもスーパークラス型の変数として扱うことができるため、サブクラスのオブジェクトをスーパークラス型の配列に代入し、それぞれのオブジェクトに対して同じメソッドを呼び出しています。
-- --
オブジェクト指向における抽象クラスの役割について解説しました。
( Written by Tatsuo Ikura )
著者 / TATSUO IKURA
これから IT 関連の知識を学ばれる方を対象に、色々な言語でのプログラミング方法や関連する技術、開発環境構築などに関する解説サイトを運営しています。