1. 序章

Polymorphism を使用すると、オブジェクトは複数の形式をとることができます。メソッドが多態性を示す場合、コンパイラはメソッドの名前を最終的な実装にマップする必要があります。

コンパイル時にマップされている場合は、静的または早期バインディングです。

実行時に解決される場合は、動的バインディングまたは遅延バインディングと呼ばれます。

2. コードによる理解

サブクラスがスーパークラスを拡張する場合、サブクラスで定義されたメソッドを再実装できます。 これは、メソッドのオーバーライドと呼ばれます。

たとえば、スーパークラス Animal:を作成しましょう。

public class Animal {

    static Logger logger = LoggerFactory.getLogger(Animal.class);

    public void makeNoise() {
        logger.info("generic animal noise");
    }

    public void makeNoise(Integer repetitions) {
        while(repetitions != 0) {
            logger.info("generic animal noise countdown " + repetitions);
            repetitions -= 1;
        }
    }
}

そしてサブクラスDog

public class Dog extends Animal {

    static Logger logger = LoggerFactory.getLogger(Dog.class);
    
    @Override
    public void makeNoise() {
        logger.info("woof woof!");
    }

}

AnimalクラスのmakeNoise()のようにメソッドをオーバーロードすると、コンパイラはコンパイル時にメソッドとそのコードを解決します。 これは静的バインディングの例です。

ただし、タイプ DogのオブジェクトをタイプAnimalの参照に割り当てると、コンパイラーは実行時に関数コードのマッピングを解決します。 これは動的バインディングです。

これがどのように機能するかを理解するために、クラスとそのメソッドを呼び出す小さなコードスニペットを書いてみましょう。

Animal animal = new Animal();

// calling methods of animal object
animal.makeNoise();
animal.makeNoise(3);

// assigning a dog object to reference of type Animal
Animal dogAnimal = new Dog();

dogAnimal.makeNoise();

The output of the above code will be:
com.baeldung.binding.Animal - generic animal noise 
com.baeldung.binding.Animal - generic animal noise countdown 3
com.baeldung.binding.Animal - generic animal noise countdown 2
com.baeldung.binding.Animal - generic animal noise countdown 1
com.baeldung.binding.Dog - woof woof!

それでは、クラスを作成しましょう。

class AnimalActivity {

    public static void eat(Animal animal) {
        System.out.println("Animal is eating");
    }

    public static void eat(Dog dog) {
        System.out.println("Dog is eating");
    }
}

これらの行をメインクラスに追加しましょう。

AnimalActivity.eat(dogAnimal);

出力は次のようになります。

com.baeldung.binding.AnimalActivity - Animal is eating

この例は、静的関数が静的バインディングを受けることを示しています。

その理由は、サブクラスが静的メソッドをオーバーライドできないためです。 サブクラスが同じメソッドを実装した場合、スーパークラスのメソッドを非表示にします。 同様に、メソッドがfinalまたはprivateの場合、JVMは静的バインディングを実行します。

静的バインドされたメソッドは特定のオブジェクトに関連付けられていませんが、 Type (Javaのクラス)で呼び出されます。 このようなメソッドの実行はわずかに高速です。

その他のメソッドは、デフォルトで自動的にJavaの仮想メソッドになります。 JVMは実行時にそのようなメソッドを解決し、これは動的バインディングです。

正確な実装はJVMによって異なりますが、C ++のようなアプローチが必要であり、JVMは仮想テーブルを検索して、メソッドが呼び出されるオブジェクトを決定します。

3. 結論

バインディングは、ポリモーフィズムを実装する言語の不可欠な部分です。静的バインディングと動的バインディングの両方の意味を理解して、アプリケーションが希望どおりに動作していることを確認することが重要です。

ただし、その理解により、クラスの継承とメソッドのオーバーロードを効果的に使用できます。

いつものように、コードはGitHubから入手できます。