Javaに関する様々な情報をご紹介します。

9オーバーライドとオーバーロード

Javaに関する様々な情報をご紹介します。

オーバーライドとオーバーロード

このページでは、オーバーライドとオーバーロードについて説明を行います。オーバーライドとは、スーパークラスで定義されたメソッドをサブクラスで再定義することを言います。オーバーロードとは、同一クラス内で、メソッド名が同一で引数の型、数、並び順が異なるメソッドを複数定義することを言います。

オーバーライド

オーバーライドとはスーパークラスにおいて定義されているインスタンスメソッドを、サブクラス内で再定義することを言います。スーパークラスのメソッドを変更することはできないが、サブクラスに特化した機能を付与する必要がある場合などに使用します。

オーバーライド

オーバーライドが適用されるのはprivateアクセスレベルを除く、インスタンスメソッドのみです。privateアクセスレベルは同一クラス内のみに参照可能なため、クラスをまたぐオーバーライドの概念には当てはまりません。スーパークラスで定義されているクラスメソッド、メンバ変数をサブクラスで再定義することは隠蔽と言われ、オーバーライドとは区別されます。

オーバーライドを定義する際には以下の規定があります。

  1. オーバーライドする側はオーバーライドされる側と戻り型、インスタンスメソッド名、引数型、引数の数が同じでなければなりません。どれか一つでも異なる場合はオーバーライドとは見なされません。
    オーバーライドする側はオーバーライドされる側と戻り型、インスタンスメソッド名、引数型、引数の数が同じでなければなりません。
  2. オーバーライドされる側のインスタンスメソッドに指定されるアクセスレベルより厳しい制限を持つアクセスレベルをオーバーライドする側のインスタンスメソッドに付与することはできません。例えばオーバーライドされる側のインスタンスメソッドにprotectedが指定されている場合、オーバーライドする側のインスタンスメソッドにprivateを指定することはできません。
  3. オーバーライドされる側のインスタンスメソッドに指定されるthrows節以外の例外をオーバーライドする側のインスタンスメソッドに指定することはできません。但し、オーバーライドされる側に指定された例外をより限定する例外をオーバーライドする側に指定することはできます。
  4. オーバーライドされる側のインスタンスメソッドにfinal修飾子が付与されている場合、そのインスタンスメソッドをオーバーライドすることはできません。
  5. オーバーライドされる側のインスタンスメソッドにabstract修飾子が付与されている場合、そのメソッドはサブクラスで必ずオーバーライドしなければなりません。オーバーライドしない場合はそのサブクラス全体がabstractクラスになります。

【例1】オーバーライドを行った例です。

class ExClass8 {
    //(1)オーバーライドされるメソッド
    void methodA(int i) {
        int x = i * 10;
    }
}
class subExClass8 extends ExClass8 {
    //(2)オーバーライドするメソッド
    void methodA(int i) {
        int x = i * 10;
        System.out.println(x);
    }
    public static void main(String[] args) {
        subExClass8 objectSub = new subExClass8();  //(3)
        objectSub.methodA(10);  //(4)
    }
}

解説1

  1. (1)スーパークラスExClass8で引数に指定された数を10倍にするメソッドmethodAを宣言します。
  2. (2)サブクラスsubExClass8でスーパークラスのmethodAをオーバーライドし、10倍された数を表示する機能を付与します。
  3. (3)サブクラスsubExClass8のオブジェクトobjectSubを宣言・生成します。
  4. (4)objectSubを通し、サブクラスでオーバーライドしたmethodAを呼び出します。

実行結果1

D:\JAVA>javac subExClass8.java

D:\JAVA>java subExClass8
100

D:\JAVA>

動的束縛と静的束縛

動的束縛とはクラス構成要素(メソッド、メンバ変数など)を呼び出す際、オブジェクト変数に代入されたオブジェクトに基づき構成要素が呼び出されることを言い、静的束縛とはオブジェクト変数のオブジェクト型に基づき構成要素が呼び出されることを言います。そのため、静的束縛はコンパイルする時点で呼び出すオブジェクトが決定されますが、動的束縛はプログラムが実行されるまでどのオブジェクトに基づき呼び出されるかわかりません(条件分岐などで、代入されるオブジェクトが変動する場合があるため)。多くのプログラム言語が静的束縛を実装する中で、動的束縛はJavaの特徴の一つとなっています。

オーバーライドは動的束縛が適用されます。一方、隠蔽は静的束縛が適用されます。以下に例を記載します。

【例2】オーバーライドを行い、動的束縛が適用される例です。

class ExClass9 {
    //(1)オーバーライドされるメソッド
    void methodA(int i) {
        System.out.println("super:" + (i * 1000));
    }
}

class subExClass9 extends ExClass9 {
    //(2)オーバーライドするメソッド
    void methodA(int i) {
        System.out.println("sub:" + (i * 10));
    }
    public static void main(String[] args) {
        //(3)オブジェクト変数の型がExClass9、
        //   オブジェクトがsubExClass9
        ExClass9 objectSuper = new subExClass9();
        objectSuper.methodA(10);  //(4)
    }
}

解説2

  1. (1)スーパークラスExClass9で引数に指定された数を1000倍にするメソッドmethodAを宣言します。
  2. (2)サブクラスsubExClass9でスーパークラスのmethodAをオーバーライドし、引数に指定された数を10倍にするメソッドmethodAを宣言します。
  3. (3)オブジェクト変数の型がExClass9でsubExClass9クラスのオブジェクトが代入されたobjectSuperを宣言・生成します。
  4. (4)objectSuperを通し、メソッドmethodAを呼び出します。オーバーライドでは、動的束縛が適用されるため、代入されるオブジェクト(サブクラスsubExClass9のオブジェクト)の構成要素のメソッドが呼び出されます。

実行結果2

D:\JAVA>javac subExClass9.java

D:\JAVA>java subExClass9
sub:100

D:\JAVA>

【例3】隠蔽を行い、静的束縛が適用される例です。

class ExClass10 {
    //(1)隠蔽されるメソッド
    static void methodA(int i) {
        System.out.println("super:" + (i * 1000));
    }
}
class subExClass10 extends ExClass10 {
    //(2)隠蔽するメソッド
    static void methodA(int i) {
        System.out.println("sub:" + (i * 10));
    }
    public static void main(String[] args) {
        //(3)オブジェクト変数の型がExClass10、
        //   オブジェクトがsubExClass10
        ExClass10 objectSuper = new subExClass10();
        objectSuper.methodA(10);  //(4)
    }
}

解説3

  1. (1)スーパークラスExClass10で引数に指定された数を1000倍にするメソッドmethodAを宣言します。
  2. (2)サブクラスsubExClass10でスーパークラスのmethodAを隠蔽し、引数に指定された数を10倍にするメソッドmethodAを宣言します。
  3. (3)オブジェクト変数の型がExClass10でsubExClass10クラスのオブジェクトが代入されたobjectSuperを宣言・生成します。
  4. (4)objectSuperを通し、メソッドmethodAを呼び出します。隠蔽では、静的束縛が適用されるため、オブジェクト変数の型のオブジェクト(スーパークラスExClass10のオブジェクト)の構成要素のメソッドが呼び出されます。

実行結果3

D:\JAVA>javac subExClass10.java

D:\JAVA>java subExClass10
super:10000

D:\JAVA>

オーバーロード

オーバーロードとは同一クラス内でメソッド名が同一で引数の型、数、並び順が異なるメソッドを複数定義することを言います。

例えば、会員登録を行う機能で、名前と国名を登録させたいとします。国名を入力しなかった会員は国名:日本で登録します。同じ登録を行う機能であるのに、メソッドをtoroku(String name,String country)、torokuJapan(String name)などと作成するするのはあまりきれいなプログラムではありません。この場合、toroku(String name)、toroku(String name,String country)というように同じ名前のメソッドを引数の数を変えて作成します。同じ機能を持つものは同じメソッド名とした方が、プログラムがきれいに見えます。Javaはメソッドの引数の型、数、並び順が異なる場合、それぞれを異なるメソッドとして扱います。これがオーバーロードの機能です

オーバーロード

オーバーロードを定義する際には以下の規定があります。

  1. 異なるメソッドと認識される部分は、メソッドの次の個所です。「引数の型」、「引数の数」、「引数の並び順」。
  2. 次の個所が異なっていても異なるメソッドとは認識されません。コンパイルエラーとなります。「戻り型」、「アクセスレベル」、「引数名」、「throws節」。

【例4】オーバーロードを行った例です。

class ExClass11{
    //(1)引数を2つ持つtorokuメソッド
    void toroku(String name, String country) {
        System.out.println("名前は" + name);
        System.out.println("国は" + country);
    }
    //(2)引数を1つ持つtorokuメソッド
    void toroku(String name) {
        System.out.println("名前は" + name);
        System.out.println("国は" + "日本");
    }
    public static void main(String[] args) {
        ExClass11 object11 = new ExClass11();
        object11.toroku("Java太郎");  //(3)
    }
}

解説4

  1. (1)引数をnameとcountryの2つ持つメソッドtorokuを宣言します。
  2. (2)引数をnameの一つしか持たず、countryに当たる部分は日本を表示するメソッドtorokuを宣言します。
  3. (3)torokuメソッドを呼び出します。引数が1つしか指定されていないため、②のメソッドが呼び出されます。

実行結果4

D:\JAVA>javac ExClass11.java

D:\JAVA>java ExClass11
名前はJava太郎
国は日本

D:\JAVA>

9オーバーライドとオーバーロード