Java での動的メソッドディスパッチ
このチュートリアルでは、Java での動的メソッドディスパッチについて説明します。技術的な定義と重要性について説明し、コード例を使用して説明します。
Java での動的メソッドディスパッチ
言葉を分解して、ディスパッチ
を呼び出す関数(メソッド)を決定するものと考えてみましょう。動的
という言葉は、実行時に決定されることを示しています。
簡単に言えば、どの関数/メソッドを実行するかは実行時に決定されると言えます。
技術的な定義を考慮すると、動的メソッドディスパッチ(ランタイムポリモーフィズムとも呼ばれます)は、コンパイル時ではなく、実行時にオーバーライドされたメソッドの呼び出しを解決するために使用されるメカニズムです。
参照を使用して子クラスのオーバーライドされたメソッドを呼び出すと、Java は、参照するオブジェクトのタイプに応じて、実行されるメソッドを決定します。次の 2つのコードのスクリーンショットを使用して、定義を理解しましょう。
次のスクリーンショットに注目してください。ここには、Shape
、Rectangle
、および Main
クラスという名前の 3つのクラスがあります。Shape
はスーパークラスであり、Rectangle
は子クラスです。
main
メソッドには、Shape
および Rectangle
タイプの 2つのオブジェクトがあり、それらの参照を shape
および rectangle
変数に保存します。
これらの変数は、それぞれのクラスの display()
メソッドを呼び出します。たとえば、shape.display()
を呼び出すと、shape
は Shape
クラスの参照を含んでいるので、コンパイル時に Shape
クラスの display()
を呼び出していると判断されます。
次に、次のスクリーンショットに示すようにコードを変更します。ここで、main
メソッドには 2つのオブジェクトが含まれています。1つは Shape
クラス用で、もう 1つは Rectangle
クラス用ですが、両方(変数 shape
と rectangle
)には Shape
クラスの参照が含まれています。
では、プログラムはどのオーバーライドされたメソッドを呼び出すべきかをどのように決定するのでしょうか?ここで、動的メソッドディスパッチがその役割を果たします。
ここで、Java は、参照するオブジェクトのタイプに応じて、実行するメソッドを決定します。
オブジェクトが Rectangle
タイプの場合、Rectangle
クラスの display()
が呼び出され、オブジェクトが Shape
タイプの場合、Shape
の display()
メソッドが呼び出されます。クラスが呼び出されます。そして、これらすべての決定は実行時に行われます。
これは、ランタイムポリモーフィズムまたは動的メソッドディスパッチと呼ばれるものです。
Java での動的メソッドディスパッチの重要性
以下の点は、動的メソッドディスパッチを使用することの重要性を高めます。
- 動的メソッドディスパッチにより、Java はランタイムポリモーフィズムに必要なメソッドオーバーライドをサポートします。
- 子クラスに機能を組み込み、プロジェクトの要件に従って実装を更新できます。
- スーパークラスがその子クラスと共有される関数/メソッドを定義し、これらの子クラスが関数の実装を更新できるようにします。
Java のコード例を使用した動的メソッドディスパッチ
サンプルコード:
class Shape {
Shape() {}
void display() {
System.out.println("I am in the Shape class");
}
}
class Rectangle extends Shape {
Rectangle() {}
void display() {
System.out.println("I am in the Rectangle class");
}
}
class Triangle extends Shape {
Triangle() {}
void display() {
System.out.println("I am in the Triangle class");
}
}
public class Main {
public static void main(String args[]) {
Shape rectangle = new Rectangle();
Shape triangle = new Triangle();
rectangle.display();
triangle.display();
}
}
出力:
I am in the Rectangle class
I am in the Triangle class
ここで、Rectangle
クラスと Triangle
クラスは Shape
クラスを拡張します。これらのクラスには、main
メソッドを呼び出すことになっている display()
メソッドがあります。
main
メソッドには 2つのオブジェクトがあります。1つは Rectangle
タイプ用で、もう 1つは Triangle
タイプ用ですが、参照変数 rectangle
と triangle
は Shape
という名前の同じ親クラスを参照します。
どの関数が呼び出されるかを見つける方法は?ここで、動的ディスパッチ方式が登場します。
次の 2つのコードコードでも動的バインディングとアップキャストを使用していることを忘れないでください。
Shape rectangle = new Rectangle();
Shape triangle = new Triangle();
動的バインディングは、オブジェクト(ここでは new Rectangle()
と new Triangle()
であるクラスのインスタンス)を使用して、実行時にメソッド呼び出しを解決します。
ここでは、親クラスの参照変数(rectangle
と triangle
)が子クラス Rectangle
と Triangle
を参照しているため、アップキャストも使用されます。