本文へスキップ
BecomeCoder

Javaオブジェクト指向コース · 第4章 多態性 ― 同じ呼び方で、違う動きをする · レッスン12

動的束縛 ― 呼ばれるメソッドは実行時に決まる

ブラウザで完結

導入

前回はそれぞれの型(Dog型、Cat型)の変数から sound() を呼びました。では、親の型(Animal型)の変数 に子のインスタンスを入れて呼んだら、どちらの sound() が実行されるでしょうか?

説明

答えは「実際に代入されているインスタンスの型」の sound() が呼ばれます。これを 動的束縛(実行時ポリモーフィズム) と呼びます。

public class Main {
    public static void main(String[] args) {
        Animal a1 = new Dog();
        Animal a2 = new Cat();
        a1.sound();
        a2.sound();
    }
}

class Animal {
    void sound() {
        System.out.println("なんらかの音");
    }
}

class Dog extends Animal {
    @Override
    void sound() {
        System.out.println("ワン");
    }
}

class Cat extends Animal {
    @Override
    void sound() {
        System.out.println("ニャー");
    }
}

a1型(見た目)は Animal ですが、実際に入っているのは Dogインスタンス(実体) です。a1.sound() を呼ぶと、変数の型ではなく 実体の型(Dog)に応じたメソッド が実行され、「ワン」と表示されます。「呼ばれるメソッドは、コンパイル時(型を見た時点)ではなく、実行時(実際のインスタンスを見た時点)で決まる」——これが動的束縛です。

やってみよう

下のエディタで Animal a1 = new Cat(); のように組み合わせを変えて実行し、いつも「実体の型」の sound() が呼ばれることを確認しましょう。

演習

Bird extends Animal を作り、sound()"チュンチュン" にオーバーライドしてください。mainAnimal a = new Bird(); として Animal 型の変数に Bird のインスタンスを代入し、a.sound() を呼んでください。

ヒント1を見る

Bird クラスの作り方はレッスン11と同じです。

ヒント2を見る

mainAnimal a = new Bird(); a.sound();。変数の型は Animal ですが、実体は Bird です。

実際に動かしてみよう

下のエディタにJavaを書いて「実行」を押すと、学習用シミュレータが System.out.println の出力を表示します(本物のJVMではなく、教材の範囲を再現した軽量エンジンです)。クラス・継承・コレクションなども動きます。Scanner で入力を読む例は「標準入力」欄に値を入れてください。本文の例を書き換えて動かしてみましょう(Stream・ラムダ・スレッド・ファイル入出力など一部の機能は対象外です)。

Java — ブラウザ内で実行(学習用シミュレータ)

Javaの教材サブセットを動かす学習用シミュレータを読み込みます(本物のJVMではなく、動きを再現した軽量な自作エンジンです)。
スクロールして表示された時点でも自動で読み込まれます。