Java入門24 abstractクラスで子クラスを束ねる

Java入門の第24回です。前回からの続きですが、今回だけでも分かる内容になっています。このシリーズの第1回はこちらです。

今回は、abstractクラス(抽象クラス)について解説します。abstractクラスは、説明だけではイメージしにくいので、具体例で理解を深めましょう。

abstractクラスとは

abstractクラスは、抽象的な概念でデータを束ねる際に使用するクラスです。複数の具体的なクラスを束ねる親クラスとして使用します。説明だけではイメージしにくいので、具体例で理解を深めましょう。

例えば、学生の情報を扱うプログラムがあるします。学生は必ずどこかの学部に所属しています。文学部に所属するAさん、工学部に所属するBさん、体育学部に所属するCさんという具合です。

学生クラスの子クラスとして文学部生クラス・工学部生クラス・体育学部生クラスがあり、 Aさんは文学部生クラスのインスタンス、Bさんは工学部生クラスのインスタンス、Cさんは体育学部生クラスのインスタンスとして管理できるでしょう。

このルール付けにおいては、どこの学部にも属さない漠然とした“学生”は存在しません。必ず文学部・工学部・体育学部のいずれかの学部に所属していなくてはなりません。

学生クラスが漠然とした学生インスタンスを生成する必要はなく、学生クラスは、あくまでも 文学部生クラス ・ 文学部生クラス ・ 文学部生クラス を束ねる抽象的なクラスに過ぎません。

この学生クラスのような抽象的なクラスは、abstractクラス(抽象クラス) として作成します。

abstractクラスの作成

abstractクラスは、以下の書式で作成します。

abstract class Gakusei {

}

上記の書式のように、abstract修飾子をつけて宣言したクラスは、 abstractクラスとして作成されます。

abstractクラスの特徴

abstractクラスの特徴は、インスタンスが生成できないということです。abstractクラスでnewキーワードを使ってインスタンスを生成しようとしてもエラーとなります。

public class Test28 {
    //abstractクラス
    abstract class Gakusei {
    }

    //インスタンスを生成しようとするとエラーになる
    Gakusei g1 = new Gakusei();
}

以下は、上記コードをEclipseで書いた際の画面です。

Eclipseの画面では、「Gakusei のインスタンスを生成できません」というエラーメッセージが表示されています。

abstractクラスの実例

abstractクラスを使ったコードの実例を確認しましょう。

//abstractクラス
abstract class Gakusei {
    public int no;
    public String name;
}
//子クラス
class Bun extends Gakusei {
    void printName() {System.out.println("文" + no + ":" + name);}
}
class Kou extends Gakusei {
    void printName() {System.out.println("工" + no + ":" + name);}
}
class Tai extends Gakusei {
    void printName() {System.out.println("体" + no + ":" + name);}
}

public class Test29 {
    public static void main(String[] args) {
        //インスタンス生成
        Bun g1 = new Bun();
        Kou g2 = new Kou();
        Tai g3 = new Tai();
        //インスタンス変数への値の代入
        g1.no = 1001; g1.name = "ヤマダ ハナコ";
        g2.no = 2001; g2.name = "スズキ タロウ";
        g3.no = 3001; g3.name = "タナカ ジロウ";
        //インスタンスメソッドを呼び出す
        g1.printName();
        g2.printName();
        g3.printName();
    }
}

上記コードの実行結果は、以下の通りです。

文1001:ヤマダ ハナコ
工2001:スズキ タロウ
体3001:タナカ ジロウ

上記コードを読む際のポイントは、学生という漠然とした立場の人物は存在しないというルール付けなので、Gakuseiクラスは抽象的なabstractクラスとして作成されています。そのため Gakuseiクラス のインスタンスは生成できません。

学生は必ずどこかの学部に所属するというルール付けなので、具体的な学生の情報は、Gakuseiクラスを継承した子クラスであるBunクラス・Kouクラス・Taiクラスのインスタンスとして生成されます。

abstractクラス内に作成するabstractメソッド

abstractクラス内には、abstractメソッドを作成できます。abstractメソッドは、以下の書式で作成します。

abstract class Gakusei {
    abstract void printName();
}

abstractメソッドは、abstractクラス内にしか作成できません。上記の書式でも、abstractクラスのなかに配置しています。

abstractメソッドは、それ自体が実行されることはありません。実行内容のない空メソッドなので、必ず子クラスでオーバーライドしてやる必要があります。

abstractメソッドの実例

abstractクラスのなかに、abstractメソッドを作成したコードの実例を確認しましょう。

//abstractクラス
abstract class Gakusei {
    public int no;
    public String name;
    //abstractメソッド
    abstract void printName();
}
//子クラス
class Bun extends Gakusei {
    void printName() {System.out.println("文" + no + ":" + name);}
}
class Kou extends Gakusei {
    void printName() {System.out.println("工" + no + ":" + name);}
}
class Tai extends Gakusei {
    void printName() {System.out.println("体" + no + ":" + name);}
}

public class Test29 {
    public static void main(String[] args) {
        //インスタンス生成
        Bun g1 = new Bun();
        Kou g2 = new Kou();
        Tai g3 = new Tai();
        //インスタンス変数への値の代入
        g1.no = 1001; g1.name = "ヤマダ ハナコ";
        g2.no = 2001; g2.name = "スズキ タロウ";
        g3.no = 3001; g3.name = "タナカ ジロウ";
        //インスタンスメソッドを呼び出す
        g1.printName();
        g2.printName();
        g3.printName();
    }
}

上記コードの実行結果は、以下の通りです。

文1001:ヤマダ ハナコ
工2001:スズキ タロウ
体3001:タナカ ジロウ

abstractメソッドを追加しても、特に実行結果が変わるわけではありません。それでもあえてabstractメソッドを追加しておくのは、このメソッドを子クラスで作成してオーバーライドすることを義務付けるためです。abstractメソッドをあえて作成しておくことで、プログラムコードの漏れがないようにチェックする役割をしてくれます。

以下は、Bunクラス内のprintName()メソッドをコメントアウトした場合のEclipseの画面です。

上記のEclipse画面では、「型 Bun は継承された抽象メソッド Gakusei.printName() を実装する必要があります」というエラーメッセージが表示されています。

これは、親クラス内にabstractメソッドとしてprintName()メソッドを作成しているのに、子クラスのBunクラスに printName()メソッドが無いことを警告されています。

まとめ

  • abstractクラスを作成するには、先頭に abstract キーワードを付けます。
  • abstractクラスは、子クラスを束ねる抽象的なクラスです。
  • abstractクラスは、インスタンスが生成できません。
  • abstractクラス内に abstractメソッドを作成したら、必ず子クラスで同じ名前のメソッドを作成してオーバーライドしてやる必要があります。

次回へ続きます。