Javaプログラムで、ある程度の開発規模になると必ず見かけることになるのが「abstract」で宣言される抽象クラスです。
abstractの存在や抽象クラスという名前は知っていても意味や使い方を理解していない方も多いのが実情です。
本記事では、Javaプログラマーの方向けにabstract(抽象クラス)の基本的な考え方と使い方をサンプルコードを交えてご紹介していきます。
目次
Javaのabstractとは
Javaでabstractは抽象クラスや抽象メソッドを定義する際に使用する修飾子です。
抽象クラスや抽象メソッドでは「具体的な処理が未定義」の状態で作成されるのが特徴です。
abstractはアクセス修飾子の1つ
abstractはpublicやprivate、protectといったアクセス修飾子の1つで下記のように記述されます。
abstract class クラス名 { abstract 戻り値の型 メソッド名(); }
抽象クラスはabstractをアクセス修飾子として宣言したクラスで、抽象メソッドを1つ以上持ちます。
抽象クラス・メソッドは継承したサブクラスで具体的な処理内容を記述する
抽象クラス・メソッドは上述した通り、具体的な処理が未定義の状態であるため、サブクラスにおいて処理内容を確定してあげる必要があります。
抽象クラスはサブクラス(子クラス)に継承されるスーパークラス(親クラス)となることが前提のクラスであり、抽象メソッドはオーバーライドされることが前提の継承元メソッドとなります。
アクセス修飾子 class クラス名 extends 抽象クラス名 { // 抽象クラスで定義したメソッドを定義し、具体的な処理を記述 }
抽象クラスは何のために定義するの?
Javaのabstract(抽象クラス)について基本的な文法や使い方を説明してきましたが、根本的に何のために定義するのでしょうか?
最も大きな理由としては、クラス設計におけるルールを仕様書レベルではなく、実装レベルで強制するために定義することです。
まず個別の処理において、ロジックは少し違うけれども似たような内容の処理を各クラスで実装することはよくあります。
抽象クラスを利用することで、複数人で開発を行う際にメソッド名やロジックをある程度統一することが出来るため、ひと目見た際にどういった処理が行われているかを把握しやすくなります。
またサブクラスでは抽象クラスで定義された抽象メソッドを必ず実装する必要がありますし、メソッド名を勝手に変更することも出来ません。
ルールを守らないとコンパイルエラーとなり、プログラム作成が出来ないことから、実装レベルでの強制力を持ったルール作りとしても役立ちます。
Javaでabstractを利用する際の注意点
Javaでabstractを利用する際に注意すべき点は大きく2つあります。
abstractで定義した抽象クラスはインスタンス化出来ない
abstractで定義した抽象クラスは他のクラスから直接インスタンス化することは出来ません。
必ずサブクラスでextends(継承)して利用する必要があります。
下記のサンプルコードでは抽象クラスとして定義したクラスをnew演算子でインスタンス化しようと試みています。
import java.io.*; public class Main { public static void main(String[] args) throws Exception { AbstractSample sample = new AbstractSample(); // インスタンス化出来ないためコンパイルエラー sample.abstractMethod(); } } abstract class AbstractSample { abstract String abstractMethod(); }
サンプルコードをコンパイルしようとすると下記の画像のようにコンパイルエラーとなることがご確認頂けます。
抽象クラスで定義した抽象メソッドは全てサブクラスで定義する必要がある
抽象クラスではまだ処理が確定していない抽象メソッドを記述していますが、サブクラスで利用する予定のない抽象メソッドもサブクラス内で定義しておく必要があります。
次のサンプルコードは抽象クラスに複数の抽象メソッドがある状態で、サブクラスで自分の利用する抽象メソッドしか定義しなかった場合の例となります。
import java.io.*; public class Main { public static void main(String[] args) throws Exception { Sample sample = new Sample(); sample.abstractMethod1(); } } abstract class AbstractSample { abstract String abstractMethod1(); abstract int abstractMethod2(); } class Sample extends AbstractSample { public String abstractMethod1() { System.out.println("abstractMethod1が呼び出されました。"); } }
SampleクラスでAbstractSampleを継承して「abstractMethod1」のみを実装しました。
コンパイルした結果が下記の画像となります。
「abstractMethod2」が継承クラスで実装されていないためコンパイルエラーとなることをご確認頂けます。
Javaでabstractを利用したサンプルコードを確認して理解を深めよう
実際にJavaプログラムでabstractを利用したサンプルコードを掲載します。
今回はCarという抽象クラスを作成し、サブクラスで2種類の車を定義していきたいと思います。
import java.io.*; public class Main { public static void main(String[] args) throws Exception { SuperCar superCar = new SuperCar(); Bus bus = new Bus(); System.out.println("SuperCarの情報を出力します。"); superCar.commonSpec(); superCar.carSpec(); System.out.println("Busの情報を出力します。"); bus.commonSpec(); bus.carSpec(); } } abstract class Car { String color; Car(String color) { this.color = color; } abstract void carSpec(); void commonSpec() { System.out.println("日本製の車です。"); System.out.println("カラーリングは" + this.color + "色です。"); } } // サブクラス1 class SuperCar extends Car { int maxSpeed = 300; public SuperCar() { super("赤"); } public void carSpec() { System.out.println("最高時速は" + this.maxSpeed + "km/hです。"); } } // サブクラス2 class Bus extends Car { int capacity = 20; public Bus() { super("白"); } public void carSpec() { System.out.println("収容人数は" + this.capacity + "人です。"); } }
実行した結果は下記の通りとなります。
SuperCarの情報を出力します。 日本製の車です。 カラーリングは赤色です。 最高時速は300km/hです。 Busの情報を出力します。 日本製の車です。 カラーリングは白色です。 収容人数は20人です。
今回のサンプルでは抽象メソッドである「carSpec」と具象メソッドと呼ばれる、処理が記述された「commonSpec」という2つのメソッドを抽象クラス「Car」に定義しました。
サブクラスには「commonSpec」メソッドを定義していませんが、抽象クラスに記述したコードが実行されていることがご確認頂けます。
また、抽象メソッドである「carSpec」ではそれぞれサブクラスで記述した異なる処理が実行されていることがわかります。
サンプルコードはあくまで一例ですが、共通処理は1つのクラスにまとめ、サブクラスで処理を上書きしたいメソッドを抽象メソッドとして定義しておくことで可読性の高いコードを作成することが可能です。
さいごに:Javaのabstractを上手く使うためにはクラス設計を理解する
本記事では、Javaのabstract(抽象クラス)について基本的な考え方や使い方をサンプルコードを交えながらご紹介してきました。
abstractは利用しなくてもプログラムを組めるため、あまり詳しく理解していない方が多いのも現状です。
しかしクラス設計を理解しabstractを上手く利用することで、大規模開発でも煩雑な実装とならずにまとまりのあるシステムが構築可能となります。
一つ上のレベルのJavaプログラマーとなるためにabstract(抽象クラス)の活用法はしっかりと学習しておきましょう。
抽象メソッドとは処理内容を記述せず、abstractで宣言されたメソッドです。