Javaの動的ポリモーフィズムと静的ポリモーフィズムの違いは何ですか?


118

誰かがJavaの動的ポリモーフィズムと静的ポリモーフィズムの違いを説明する簡単な例を提供できますか?


4
オーバーライドは、「静的ポリモーフィズム」と呼ばれることもあります。これは少し伸びますが、それは起こっていることです。
dasblinkenlight 2013

@dasblinkenlight情報をありがとう。その例はありますか?
Prabhakar Manthena 2013

「メソッドのオーバーロード」と「メソッドのオーバーライド」を検索します。
dasblinkenlight 2013

5
オーバーロードが多態性であることを理解していません。ポリモーフィズムはオブジェクトの概念です。オブジェクトBをオブジェクトAとして表示できるはずです。以下の(回答)の例では、犬を動物として表示しているため、多型です。しかし、オーバーロードでは、「同じ名前」を使用して別のメソッドを呼び出しています。これはどのように多態性であることができます。したがって、「静的バインディング」は正しい用語ですが、オーバーロードの場合は静的多型ではありません。
Punith Raj 2014

@PunithRajあなたはおそらくサブタイプポリモーフィズムを参照しています。オーバーロードに適用されるアドホックと呼ばれる別の種類があります。
ケルビン

回答:


196

ポリモーフィズム

1.静的バインディング/コンパイル時バインディング/早期バインディング/メソッドのオーバーロード(同じクラス内)

2.動的バインディング/実行時バインディング/遅延バインディング/メソッドのオーバーライド。(異なるクラスで)

オーバーロードの例:

class Calculation {  
  void sum(int a,int b){System.out.println(a+b);}  
  void sum(int a,int b,int c){System.out.println(a+b+c);}  

  public static void main(String args[]) {  
    Calculation obj=new Calculation();  
    obj.sum(10,10,10);  // 30
    obj.sum(20,20);     //40 
  }  
}  

オーバーライドの例:

class Animal {    
   public void move(){
      System.out.println("Animals can move");
   }
}

class Dog extends Animal {

   public void move() {
      System.out.println("Dogs can walk and run");
   }
}

public class TestDog {

   public static void main(String args[]) {
      Animal a = new Animal(); // Animal reference and object
      Animal b = new Dog(); // Animal reference but Dog object

      a.move();//output: Animals can move

      b.move();//output:Dogs can walk and run
   }
}

6
私はJavaを初めて使用するので、の根底にあるコンセプトは何ですか?Animal reference but Dog objectなぜ使用できないのDog reference and dog objectですか?
pratyay

3
上記の例では、ポリモーフィズムの概念を示しました。同じクラスの参照とオブジェクトを作成できますが、メソッドのオーバーライドを実現できません。ポスト以下で通過してください: stackoverflow.com/questions/12159601/...
カーンサーブ

メソッドのオーバーロードはコンパイル時のポリモーフィズムです。同じ方法です。コンストラクタのオーバーロードもコンパイル時のポリモーフィズムですか?
Gaali Prabhakar、

29
  • メソッドのオーバーロードは静的なポリモーフィズムの例です

  • 一方、オーバーライドは動的なポリモーフィズムの例です。

    オーバーロードの場合は、コンパイル時にコンパイラが呼び出しにリンクするメソッドを認識しているためです。ただし、動的ポリモーフィズムは実行時に決定されます


17

動的(実行時)ポリモーフィズムは、実行時に存在したポリモーフィズムです。ここでは、Javaコンパイラーはコンパイル時に呼び出されるメソッドを理解していません。実行時に呼び出されるメソッドを決定するのはJVMだけです。メソッドのオーバーロードとインスタンスメソッドを使用したメソッドのオーバーライドは、動的なポリモーフィズムの例です。

例えば、

  • さまざまな種類のドキュメントをシリアル化および逆シリアル化するアプリケーションを考えてみましょう。

  • 基本クラスとして 'Document'を持ち、それから派生するさまざまなドキュメントタイプクラスを持つことができます。たとえば、XMLDocument、WordDocumentなど。

  • ドキュメントクラスは 'Serialize()'および 'De-serialize()'メソッドを仮想として定義し、各派生クラスはドキュメントの実際のコンテンツに基づいて独自の方法でこれらのメソッドを実装します。

  • さまざまなタイプのドキュメントをシリアル化/シリアル化解除する必要がある場合、ドキュメントオブジェクトは「Document」クラス参照(またはポインタ)によって参照され、「Serialize()」または「De-serialize()」メソッドが呼び出されたときにその上で、仮想メソッドの適切なバージョンが呼び出されます。

静的(コンパイル時)多態性は、コンパイル時に示される多態性です。ここで、Javaコンパイラーはどのメソッドが呼び出されるかを認識しています。静的メソッドを使用したメソッドのオーバーロードとメソッドのオーバーライド。プライベートメソッドまたはfinalメソッドを使用してオーバーライドするメソッドは、静的ポリモーフィズムの例です。

例えば、

  • 従業員オブジェクトには2つのprint()メソッドがあり、1つは引数を取らず、もう1つは従業員データとともに表示されるプレフィックス文字列を取ります。

  • これらのインターフェースの場合、引数なしでprint()メソッドが呼び出されると、コンパイラーは関数の引数を見て、どの関数が呼び出されるかを認識し、それに応じてオブジェクトコードを生成します。

詳細については、「ポリモーフィズムとは」(Google it)をお読みください。


2
エラーの完全なこの答え:(1)メソッドのオーバーロードは動的なポリモーフィズムではありません。静的なポリモーフィズムです。(2)静的メソッドはオーバーライドされないため、非表示/シャドウになります。(3)プライベートメソッドは「オーバーライド」されません。そもそも継承されることはありません。
ジョンレッド

14

バインディングとは、メソッド呼び出しとメソッド定義の間のリンクを指します。

この写真は、拘束力のあるものを明確に示しています。

拘束

この図では、「a1.methodOne()」呼び出しは対応するmethodOne()定義にバインドされており、「a1.methodTwo()」呼び出しは対応するmethodTwo()定義にバインドされています。

すべてのメソッド呼び出しには、適切なメソッド定義が必要です。これはJavaのルールです。コンパイラーがすべてのメソッド呼び出しの適切なメソッド定義を認識しない場合、エラーがスローされます。

ここで、Javaの静的バインディングと動的バインディングについて説明します。

Javaの静的バインディング:

静的バインディングは、コンパイル中に発生するバインディングです。プログラムが実際に実行される前にバインディングが行われるため、事前バインディングとも呼ばれます。

静的バインディングは、下の図のように示されます。

ここに画像の説明を入力してください

この図では、 'a1'はクラスAのオブジェクトを指すクラスAの参照変数です。'a2 'もクラスAの参照変数ですが、クラスBのオブジェクトを指します。

コンパイル中、バインド中、コンパイラは特定の参照変数が指しているオブジェクトのタイプをチェックしません。メソッドが呼び出される参照変数のタイプをチェックし、そのタイプのメソッド定義が存在するかどうかをチェックするだけです。

たとえば、上の図の「a1.method()」メソッド呼び出しの場合、コンパイラーはクラスAにmethod()のメソッド定義が存在するかどうかをチェックします。「a1」はクラスAタイプなので、同様に、「a2.method()」メソッド呼び出しの場合、クラスAにmethod()のメソッド定義が存在するかどうかを確認します。「a2」もクラスAタイプであるためです。'a1'と 'a2'が指しているオブジェクトはチェックしません。このタイプのバインディングは静的バインディングと呼ばれます。

Javaの動的バインディング:

動的バインディングは、実行時に発生するバインディングです。プログラムが実際に実行されているときにバインディングが発生するため、遅延バインディングとも呼ばれます。

実行時には、実際のオブジェクトがバインドに使用されます。たとえば、上の図の「a1.method()」呼び出しでは、「a1」が指している実際のオブジェクトのmethod()が呼び出されます。「a2.method()」呼び出しでは、「a2」が指している実際のオブジェクトのmethod()が呼び出されます。このタイプのバインディングは動的バインディングと呼ばれます。

上記の例の動的バインディングは、以下のように示すことができます。

ここに画像の説明を入力してください

参考静的結合-および動的結合-Javaで


前より良い。
AnBisw 2017

8

ポリモーフィズム: ポリモーフィズムは、オブジェクトがさまざまな形をとる能力です。OOPでのポリモーフィズムの最も一般的な使用法は、親クラス参照を使用して子クラスオブジェクトを参照する場合に発生します。

動的バインディング/実行時ポリモーフィズム:

実行時のポリモーフィズムは、メソッドのオーバーライドとも呼ばれます。このメカニズムでは、オーバーライドされた関数の呼び出しが実行時に解決されます。

public class DynamicBindingTest {

    public static void main(String args[]) {
        Vehicle vehicle = new Car(); //here Type is vehicle but object will be Car
        vehicle.start();       //Car's start called because start() is overridden method
    }
}

class Vehicle {

    public void start() {
        System.out.println("Inside start method of Vehicle");
    }
}

class Car extends Vehicle {

    @Override
    public void start() {
        System.out.println("Inside start method of Car");
    }
}

出力:

車内スタート方法

静的バインディング/コンパイル時のポリモーフィズム:

どのメソッドを呼び出すかは、コンパイル時にのみ決定されます。

public class StaticBindingTest {

    public static void main(String args[])  {
       Collection c = new HashSet();
       StaticBindingTest et = new StaticBindingTest();
       et.sort(c);

    }

    //overloaded method takes Collection argument
    public Collection sort(Collection c){
        System.out.println("Inside Collection sort method");
        return c;
    }


   //another overloaded method which takes HashSet argument which is sub class
    public Collection sort(HashSet hs){
        System.out.println("Inside HashSet sort method");
        return hs;
    }

}

出力:Inside Collection sort metho


8

メソッドのオーバーロードは、コンパイル時/静的ポリモーフィズムの例です。これは、メソッド呼び出しとメソッド定義の間のメソッドバインディングがコンパイル時に発生し、クラスの参照(コンパイル時に作成され、スタックに移動する参照)に依存するためです。

メソッドのオーバーライドと実行時/動的ポリモーフィズムの例は、メソッド呼び出しとメソッド定義の間のメソッドバインディングが実行時に発生し、クラスのオブジェクト(実行時に作成されてヒープに移動するオブジェクト)に依存するためです。


*(オブジェクトが実行時に作成し、ヒープに行く)、それは時間を実行する必要があります
ミート

7

簡単な言葉で :

静的ポリモーフィズム:同じメソッド名が、同じクラスの異なる型または数のパラメーターでオーバーロードされています(異なるシグニチャー)。ターゲットメソッドの呼び出しはコンパイル時に解決されます。

動的ポリモーフィズム:同じメソッドが異なるクラスの同じシグネチャでオーバーライドさます。メソッドが呼び出されているオブジェクトのタイプはコンパイル時には不明ですが、実行時に決定されます。

一般的に、オーバーロードはポリモーフィズムとは見なされません。

Javaチュートリアルページから:

クラスのサブクラスは、独自の動作を定義しながら、親クラスと同じ機能の一部を共有できます


Generally overloading won't be considered as polymorphism.この点について詳しく教えてください。
プライム

1
動的なバインディングとオーバーライドは、ポリモーフィズムの顕著なポイントです
Ravindra babu

5

メソッドのオーバーロード静的ポリモーフィズムと呼ばれ、コンパイル時ポリモーフィズムまたは静的バインディングとも呼ばれますます。オーバーロードされたメソッド呼び出しは、引数リストと、メソッドを呼び出す参照に基づいて、コンパイラーによってコンパイル時に解決されるためです。

また、オーバーライドされたメソッド呼び出しは実行時に解決されるため、メソッドのオーバーライドは、動的ポリモーフィズムまたは単純なポリモーフィズムまたはランタイムメソッドディスパッチまたはダイナミックバインディングとして知られています。

なぜそうなのかを理解するためにMammalHumanクラスとクラスの例を見てみましょう

class Mammal {
    public void speak() { System.out.println("ohlllalalalalalaoaoaoa"); }
}

class Human extends Mammal {

    @Override
    public void speak() { System.out.println("Hello"); }

    public void speak(String language) {
        if (language.equals("Hindi")) System.out.println("Namaste");
        else System.out.println("Hello");
    }

}

以下のコード行に出力とバイトコードを含めました

Mammal anyMammal = new Mammal();
anyMammal.speak();  // Output - ohlllalalalalalaoaoaoa
// 10: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V

Mammal humanMammal = new Human();
humanMammal.speak(); // Output - Hello
// 23: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V

Human human = new Human();
human.speak(); // Output - Hello
// 36: invokevirtual #7 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:()V

human.speak("Hindi"); // Output - Namaste
// 42: invokevirtual #9 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:(Ljava/lang/String;)V

上記のコードを見ると、humanMammal.speak()、human.speak()、およびhuman.speak( "Hindi")のバイトコードは、コンパイラが引数リストに基づいて区別できるため、まったく異なることがわかります。およびクラス参照。これが、メソッドのオーバーロード静的ポリモーフィズムとして知られている理由ですです。

しかし、anyMammal.speak()とhumanMammal.speak()のバイトコードは同じです。コンパイラによれば、両方のメソッドが哺乳類参照で呼び出されますが、実行時にJVMは参照が保持しているオブジェクトとJVM呼び出しを知っているため、両方のメソッド呼び出しの出力は異なります。オブジェクトのメソッド。これがメソッドのオーバーライドが動的ポリモーフィズムとして知られている理由です。

したがって、上記のコードとバイトコードから、コンパイル段階でメソッドの呼び出しが参照型から考慮されることは明らかです。ただし、実行時には、参照が保持しているオブジェクトからメソッドが呼び出されます。

これについて詳しく知りたい場合は、JVMによるメソッドのオーバーロードと内部でのオーバーライドの処理方法を参照してください


3

静的多態性: どの方法を実行するかを解決する決定は、コンパイル時に決定される場所です。メソッドオーバーロードは、この例です。

動的ポリモーフィズム: 実行時にどのメソッドを選択するかを決定する場所です。メソッドオーバーライドはこの例です。


3

多態性とは、同じトリガーに対して異なる動作をするオブジェクトの機能を指します。

静的ポリモーフィズム(コンパイル時ポリモーフィズム)

  • 静的ポリモーフィズムは、コンパイル時に実行するメソッドを決定します。
  • メソッドのオーバーロードは静的なポリモーフィズムの例であり、静的なポリモーフィズムを発生させる必要があります。
  • 静的ポリモーフィズムは、静的バインディングによって実現されます。
  • 静的ポリモーフィズムは同じクラスで発生します。
  • 静的なポリモーフィズムにはオブジェクトの割り当ては必要ありません。
  • 静的多型には継承は含まれません。

動的ポリモーフィズム(実行時ポリモーフィズム)

  • 動的ポリモーフィズムは、実行時に実行するメソッドを決定します。
  • メソッドのオーバーライドは動的なポリモーフィズムの例であり、動的なポリモーフィズムを発生させる必要があります。
  • 動的ポリモーフィズムは、動的バインディングによって実現されます。
  • 動的ポリモーフィズムは、異なるクラス間で発生します。
  • 動的ポリモーフィズムのために、サブクラスオブジェクトがスーパークラスオブジェクトに割り当てられている場合に必要です。
  • 動的ポリモーフィズムに含まれる継承。

1

コンパイル時のポリモーフィズム(静的バインディング/早期バインディング):静的ポリモーフィズムでは、コードでメソッドを呼び出すと、そのメソッドのどの定義が実際に呼び出されるかは、コンパイル時にのみ解決されます。

(または)

コンパイル時に、Javaはメソッドシグネチャをチェックすることにより、どのメソッドを呼び出すかを認識します。したがって、これはコンパイル時のポリモーフィズムまたは静的バインディングと呼ばれます。

動的ポリモーフィズム(遅延バインディング/実行時ポリモーフィズム):実行時に、Javaは実行時まで待機して、参照によって実際に参照されているオブジェクトを判別します。メソッドの解決は実行時に行われました。これは、ランタイムポリモーフィズムと呼ばれるためです。


1

以下のコードを検討してください:

public class X
{
    public void methodA() // Base class method
    {
        System.out.println ("hello, I'm methodA of class X");
    }
}

public class Y extends X
{
    public void methodA() // Derived Class method
    {
        System.out.println ("hello, I'm methodA of class Y");
    }
}
public class Z
{
public static void main (String args []) {

    //this takes input from the user during runtime
    System.out.println("Enter x or y");
    Scanner scanner = new Scanner(System.in);
    String value= scanner.nextLine();

    X obj1 = null;
    if(value.equals("x"))
        obj1 = new X(); // Reference and object X
    else if(value.equals("y"))
        obj2 = new Y(); // X reference but Y object
    else
        System.out.println("Invalid param value");

    obj1.methodA();
}
}

コードを見ると、実行時にmethodA()のどの実装が実行されるかはわかりません。これは、実行時にユーザーが指定する値に依存するためです。したがって、どのメソッドが呼び出されるかは、実行時にのみ決定されます。したがって、ランタイムポリモーフィズム。


0

メソッドのオーバーロードはコンパイル時のポリモーフィズムです。例を見て、概念を理解しましょう。

class Person                                            //person.java file
{
    public static void main ( String[] args )
    {
      Eat e = new Eat();
       e.eat(noodle);                                //line 6
    }

   void eat (Noodles n)      //Noodles is a object    line 8                     
   {

   }
   void eat ( Pizza p)           //Pizza is a object
  {

  }

}

この例では、Personにeatメソッドがあり、PizzaまたはNoodlesのいずれかを食べることができることを表しています。このPerson.javaをコンパイルすると、メソッドeatがオーバーロードされます。コンパイラは、メソッド呼び出し "e.eat(noodles)[6行目]]を8行目に指定されたメソッド定義で解決します。つまり、noodlesをパラメータとして受け取るメソッドです。プロセス全体がコンパイラによって行われるため、コンパイル時のポリモーフィズムになります。メソッド呼び出しをメソッド定義で置き換えるプロセスはバインディングと呼ばれます。この場合、コンパイラによって行われるため、アーリーバインディングと呼ばれます。


0

Nareshの回答に続き、動的ポリモーフィズムはJavaでは「動的」に過ぎません。これは、仮想マシンが存在し、ネイティブに実行されているコードではなく実行時にコードを解釈する機能があるためです。

C ++では、明らかにgccを使用してネイティブバイナリにコンパイルされている場合、コンパイル時に解決する必要があります。ただし、仮想テーブルでのランタイムジャンプとサンクは、引き続き「ルックアップ」または「ダイナミック」と呼ばれます。CがBを継承し、を宣言するとB* b = new C(); b->method1();、bはC内のBオブジェクトを指すようにコンパイラーによって解決されます(単純なクラスがクラスの状況を継承する場合、CとC内のBオブジェクトは同じメモリアドレスから始まるため、何もありません。実行する必要があります。両方が使用するvptrをポイントします)。CがBとAを継承する場合、method1のCエントリ内のAオブジェクトの仮想関数テーブルには、カプセル化しているCオブジェクトの先頭へのポインターをオフセットし、それを実際のA :: method1()に渡すサンクがあります。 Cがオーバーライドしたテキストセグメント内。ためにC* c = new C(); c->method1()、cはすでに外側のCオブジェクトを指しており、ポインタはテキストセグメントのC :: method1()に渡されます。参照:http : //www.programmersought.com/article/2572545946/

Javaでは、のB b = new C(); b.method1();場合、仮想マシンはbとペアになっているオブジェクトのタイプを動的にチェックし、正しいポインタを渡して正しいメソッドを呼び出すことができます。仮想マシンの追加のステップにより、コンパイル時に既知である場合でも、コンパイル時に解決される仮想関数テーブルまたは型の必要がなくなります。これは、仮想マシンが関与し、コードがバイトコードにのみコンパイルされる場合に意味のある別の方法です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.