KATOエンジニヤリング開発日誌

「アウトプット無きエンジニアにインプットもチャンスも無い」の精神で書いています

Javaの抽象クラスについて学ぶ

「Javaプログラミング技法」の第11回目の授業内容まとめになります。

※前回授業内容の内容はこちら

www.kato-eng.info

抽象クラス

抽象クラスとはフィールド、メソッド、コンストラクタを宣言することはできるが、インスタンスを生成することができない特殊なクラスのことをいう。また、抽象クラスは処理を定義していない抽象メソッドを定義することができる。つまり抽象クラスはサブクラスを作ることを前提としたクラスである。

抽象クラスを継承してインスタンスを生成するクラスを具象クラスという。具象クラスはこれまでの授業で使用していた通常のクラスなので、処理を定義していない抽象メソッドを定義することはできない。処理を定義するメソッドは具象メソッドという。

抽象クラスの宣言方法

抽象クラスを宣言するにはクラスの宣言時に「abstract」キーワード付ける。

abstract class クラス名 {
    フィールドの宣言;

    メソッドの宣言 {
        ...
    }

    // 抽象メソッドの定義
    abstract 戻り値の型 メソッド名(引数);
}

抽象メソッドを定義するにはメソッド名の前に「abstract」キーワードを付ける。メソッドの処理は定義しないのでメソッド名の後に「;(セミコロン)」を付ける。

抽象クラスの利用例

抽象クラスとしてMyAbst.javaを作成。

// MyAbst.java

package jpt11;

abstract class MyAbst {
    // 通常のフィールドでサブクラスに継承される
    protected int x;

    /*
     * 抽象クラスでもコンストラクタを作成することができる。
     * サブクラスでコンストラクタが実行された際に最初に呼び出される。
     */
    public MyAbst() {
        System.out.println("MyAbst()");
        this.x = 10;
    }

    // 通常のメソッドでサブクラスに継承される
    public int getX() {
        return x;
    }

    // 抽象メソッドでサブクラスで処理を実装する必要がある
    public abstract void method();
}

抽象クラスを継承するサブクラスとしてMySub.javaを作成。

// MySub.java
package jpt11;

public class MySub extends MyAbst {
    private int y;

    public MySub() {
        /*
         * コンストラクタの先頭でスーパークラスのMyAbstのコンストラクタが呼び出される。
         * その後、以下の処理が実行される。
         */
        System.out.println("MySub()");
        this.y = 20;
    }

    // 抽象クラスで定義した抽象メソッドはサブクラスで実装しないとコンパイルエラーになる
    @Override
    public void method() {
        super.x = super.x + 1;
    }
}

mainメソッドを定義して実行する。

// Ex00.java

package jpt11;

public class Ex00 {

    public static void main(String[] args) {
        // 抽象クラスのインスタンスは生成できない
        //MyAbst ma = new MyAbst();

        // 抽象クラスを継承したサブクラスのインスタンスは生成できる
        MySub ms = new MySub();

        // 抽象クラスの変数にサブクラスのインスタンスを代入することはできる
        MyAbst ma = new MySub();
    }
}

出力結果は下記の通り。

MyAbst()
MySub()
MyAbst()
MySub()

抽象クラスはサブクラスの共通機能の集約が目的である。

インスタンスのクラスを調べる

継承や抽象クラスを利用するプログラムでは、サブクラスの種類や数が増える。これらの多くはスーパークラスの変数で扱われる。インスタンスの型を調べるには「instanceof」演算子を使用する。

instanceof演算子の使い方

インスタンスを指す変数 instanceof クラス名

左辺の変数が指すインスタンスが右辺のクラス、または右辺のサブクラスであればtrueを返し、そうでなければfalseを返す。

// HighSchoolStudent.java

package jpt11;

public class HighSchoolStudent extends Student {
    public int id;
}
// UniversityStudent.java

package jpt11;

public class UniversityStudent extends Student {
    public int id;
}
// Student.java

package jpt11;

public class Student {
    public static void main(String[] args) {
        Student[] students = new Student[2];
        students[0] = new HighSchoolStudent();
        students[1] = new UniversityStudent();

        // students[0]はStudentクラスのサブクラスである
        if (students[0] instanceof Student) {
            System.out.println("学生");
        }

        // students[0]はHighSchoolStudentクラスである
        if (students[0] instanceof HighSchoolStudent) {
            System.out.println("高校生1");
        }

        // students[1]はHighSchoolStudentクラスではない
        if (students[1] instanceof HighSchoolStudent) {
            // これは出力されない
            System.out.println("高校生2");
        }
    }
}

出力結果は下記の通り。

学生
高校生1