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に依存しますが、メソッドが呼び出されるオブジェクトを決定するためにJVMが仮想テーブルをルックアップするC ++のようなアプローチを取ります。

3.まとめ

バインディングは多態性を実装する言語の不可欠な部分です。スタティックバインディングとダイナミックバインディングの両方の意味を理解して、アプリケーションが意図したとおりに動作することを確認することが重要です。

しかし、そのことを理解していれば、クラスの継承とメソッドのオーバーロードを効果的に使用できます。

いつものように、コードはhttps://github.com/eugenp/tutorials/tree/master/core-java-lang[over GitHub]から入手できます。