【タイトル】抽象クラス / 抽象メソッド / abstract修飾子
オブジェクト指向 プログラミングで、安全な「継承の材料」を実現するために、「共通の性質を持つクラスをまとめるためのクラス」です。
abstract は「抽象的」、「理論的」、「観念的」という意味を持つ。
【説明】抽象クラス、抽象メソッド、abstract修飾子とは?
「継承の材料」になるクラスを作るとなると以下のような心配事が出てきます。
抽象クラス
、抽象メソッド
はそれらを解決する仕組みといえます。
abstract修飾子
は 「それらを定義するための修飾子」 です。
abstract修飾子
【説明】abstract修飾子とは
抽象メソッドを含むクラスは抽象クラスと呼ばれ、abstract修飾子
を付与しなければいけません。
【使用場面】
Javaで抽象クラス
、抽象メソッド
を作成する時
【基本構文】
抽象クラスの定義時、「 abstract修飾子を クラス名とメソッド名の前に記述 」します。
abstract class クラス名{
abstract 戻り値の型 メソッド名(引数の型 引数);
}
抽象クラスと具象クラス
Javaには 具象クラス
と 抽象クラス
の2種類がありこれらの違いを比べてみます。
具象クラス
具象クラスとは、具象という単語が意味する通り「具象メソッド(処理を記述したメソッド)の集まり」です。
抽象クラス
抽象クラスとはインターフェースと通常のクラスの中間のようなクラスで、「 抽象メソッド(処理の記述がないメソッド)が1つ以上持つクラス 」のことです。
抽象クラスは自身だけでは意味をもたず、サブクラスに継承されることで初めて機能します。
抽象クラスの特徴
特徴についてのまとめは以下です。
- 処理の中身を記述しない
- 多重継承はできない
- 直接インスタンス化して使用できない。
- インスタンス化するには、抽象クラスを継承した具象クラスで全ての抽象メソッドをオーバーライドする必要がある。
- サブクラスでコンストラクタを記述しなければならない
- 抽象クラスの抽象メソッドは宣言のみ
抽象クラスのメリット
一見不便な点が目立つ抽象クラス
を用いる利点は以下のように「メンテナンス性がとても優れている」ことです。
- コンパイラのチェック機構により、コーディングミスの早期発見が可能
- オーバーライドすべきメソッドが一目で分かるため、ソースの可読性が向上
- 階層化により、プログラムの保守性が高い
- メソッド名の統一とロジックを共通化によって処理を把握しやすい
- 共通の処理を全てのクラスに書き込む必要がなくなる
- 複数人で開発を行う場合に実装レベルのルールを作れる
【使用場面】
- 「絶対的な決まり」を正確に実施させたい場合
- 多重継承させたくない 場合
【基本構文】
以下のようにクラス名、メソッド名の前にabstractキーワードを記述します。
abstract class クラス名{
抽象メソッド
}
抽象メソッド
【説明】
抽象メソッドは「 抽象クラス内の abstract が付いたメソッド 」です。
抽象メソッドのメリット
抽象メソッドのオーバーライドによって、
「 コーディングの時点ではどこに挿入するかは決まってないが、いずれ必要となるメソッド 」をあらかじめ宣言しておき、詳細は後のクラスで定義するといったコーディングが可能です。
【抽象メソッドの宣言】
抽象メソッド
は、抽象クラス
を継承するクラスでのオーバーライドと中身の処理の実装が必須です。
「派生クラスで抽象メソッドを使うには、抽象クラスを「extends」句で継承する」必要があります。
abstract class 抽象クラス名 {
abstract 戻り値の型名 メソッド名(引数);
}
class 派生クラス名 extends 抽象クラス名 {
戻り値の型名 メソッド名(引数) {
処理内容;
}
}
【サンプルコード】 「食べ物」という抽象クラスから「カレー」と「チョコ」という具象クラスを生成
抽象クラス「Foods」と、それを継承する具象クラス2つ(Curry, Chocolate)を作成します。
抽象クラスで実装したメソッドにより、動作が変化することを確認しましょう。
【Mainクラス】Main.java
public class Main {
public static void main(String[] args) {
Foods curry = new Curry(); // Curryクラスをインスタンス化
curry.foodTaste(); //foodTasteメソッドを呼び出す
Foods choco = new Chocolate();// Chocolateクラスをインスタンス化
choco.foodTaste(); //foodTasteメソッドを呼び出す
}
}
【抽象クラス】Foods.java
//抽象クラス (食べ物)
//abstract修飾子を付けて「抽象クラス」
abstract class Foods {
private String name;
public Foods(String name) {
this.name = name;
}
// 食べ物の味を出力。
public void foodTaste() {
System.out.println(name + "の味は: " + taste());
}
// 「抽象メソッドの呼び出し」ため、abstract修飾子を使用。
// 具象クラスからのみアクセスするため、protected修飾とする
abstract protected String taste();
}
【具象クラス】Curry.java
// 抽象クラスの「Foods」を継承する
public class Curry extends Foods {
public Curry() {
super("カレー");
}
// メソッドを実装する
protected String taste() {
return "辛い";
}
}
【具象クラス】Chocolate.java
//抽象クラスの「Foods」を継承する
public class Chocolate extends Foods {
public Chocolate() {
super("チョコレート");
}
// メソッドを実装する
protected String taste() {
return "甘い";
}
}
【実行結果】
カレーの味は: 辛い
チョコレートの味は: 甘い
サンプルコード解説
- 抽象クラス Foods を作成し、foodTasteメソッド を 抽象メソッド とします。
- 具象クラスCurryを作成し、Foodsクラス を継承。
- 続いて foodTasteメソッド を実装し、同様に具象クラス Chocolateクラス を作成
- Curryクラス、Chocolateクラス のインスタンスを作成し、
- foodTasteメソッド を呼びます。
- 次に具象メソッドの実装に従い、インスタンスの動作が変化します。
- ただ、Foodsクラス をインスタンス化できないことに注意。
【まとめ】
JavaSilverの範囲でも抽象クラス / 抽象メソッド / abstract修飾子 についてはかならず出るとのことなので、しくみはかくじつにおさえておきたいところです。