Quelle est la différence entre le polymorphisme dynamique et statique en Java?


118

Quelqu'un peut-il fournir un exemple simple qui explique la différence entre le polymorphisme dynamique et statique en Java?


4
Les remplacements sont parfois appelés «polymorphisme statique». Cela étire un peu les choses, mais c'est ce qui se passe.
dasblinkenlight

@dasblinkenlight merci pour l'info. y a-t-il un exemple pour cela ??
Prabhakar Manthena

Recherchez «surcharge de méthode» et «remplacement de méthode».
dasblinkenlight

5
Je ne comprends pas à quel point la surcharge est le polymorphisme. Le polymorphisme est un concept d'objet. nous devrions pouvoir montrer l'objet B en tant qu'objet A. à partir de ci-dessous (réponse), vous montrez un chien comme un animal et c'est donc un polymorphisme. Mais en surcharge, vous appelez une méthode différente mais avec le «même nom». Comment cela peut-il être du polymorphisme. Par conséquent, "liaison statique" est le terme correct à utiliser, mais le polymorphisme statique ne l'est pas en cas de surcharge.
Punith Raj

@PunithRaj Vous faites probablement référence au polymorphisme des sous-types . Il existe un autre type appelé Ad hoc qui s'applique à la surcharge.
Kelvin

Réponses:


196

Polymorphisme

1. Liaison statique / liaison à la compilation / liaison anticipée / surcharge de méthode (dans la même classe)

2. Liaison dynamique / Liaison d'exécution / Liaison tardive / Remplacement de méthode (dans différentes classes)

exemple de surcharge:

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 
  }  
}  

exemple primordial:

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
Je suis nouveau sur Java, donc juste curieux de savoir quel est le concept sous-jacent Animal reference but Dog object, pourquoi ne pouvons-nous pas utiliser Dog reference and dog object?
pratyay

3
Dans l'exemple ci-dessus, j'ai essayé de montrer le concept de polymorphisme. nous pouvons créer la référence et l'objet de la même classe mais nous ne pouvons pas remplacer la méthode. s'il vous plaît passer par le post ci-dessous: stackoverflow.com/questions/12159601/…
KhAn SaAb

la surcharge de méthode est un polymorphisme au moment de la compilation. est la même manière. est-ce que la surcharge du constructeur est également le polymorphisme de la compilation?
Gaali Prabhakar

29
  • La surcharge de méthode serait un exemple de polymorphisme statique

  • alors que le dépassement serait un exemple de polymorphisme dynamique.

    Car, en cas de surcharge, au moment de la compilation, le compilateur sait quelle méthode lier à l'appel. Cependant, il est déterminé à l'exécution pour le polymorphisme dynamique


17

Le polymorphisme dynamique (à l'exécution) est le polymorphisme qui existait à l'exécution. Ici, le compilateur Java ne comprend pas quelle méthode est appelée au moment de la compilation. Seule la JVM décide quelle méthode est appelée au moment de l'exécution. La surcharge de méthode et le remplacement de méthode à l'aide de méthodes d'instance sont des exemples de polymorphisme dynamique.

Par exemple,

  • Considérez une application qui sérialise et désérialise différents types de documents.

  • Nous pouvons avoir 'Document' comme classe de base et différentes classes de type de document qui en dérivent. Par exemple, XMLDocument, WordDocument, etc.

  • La classe de document définira les méthodes «Serialize ()» et «De-serialize ()» comme virtuelles et chaque classe dérivée implémentera ces méthodes à sa manière en fonction du contenu réel des documents.

  • Lorsque différents types de documents doivent être sérialisés / dé-sérialisés, les objets de document seront référencés par la référence de classe 'Document' (ou pointeur) et lorsque la méthode 'Serialize ()' ou 'De-serialize ()' est appelée dessus, les versions appropriées des méthodes virtuelles sont appelées.

Le polymorphisme statique (au moment de la compilation) est le polymorphisme présenté au moment de la compilation. Ici, le compilateur Java sait quelle méthode est appelée. Surcharge de méthode et remplacement de méthode à l'aide de méthodes statiques; le remplacement de méthode à l'aide de méthodes privées ou finales sont des exemples de polymorphisme statique

Par exemple,

  • Un objet employé peut avoir deux méthodes print (), l'une ne prenant aucun argument et l'autre prenant une chaîne de préfixe à afficher avec les données de l'employé.

  • Étant donné ces interfaces, lorsque la méthode print () est appelée sans aucun argument, le compilateur, en regardant les arguments de la fonction, sait quelle fonction est censée être appelée et génère le code objet en conséquence.

Pour plus de détails, veuillez lire "Qu'est-ce que le polymorphisme" (Google it).


2
Cette réponse pleine d'erreurs: (1) La surcharge de méthode n'est pas un polymorphisme dynamique. C'est un polymorphisme statique. (2) Les méthodes statiques ne sont jamais remplacées, elles sont masquées / ombrées. (3) Les méthodes privées ne sont pas "écrasées". Ils ne sont jamais hérités en premier lieu.
John Red

15

La liaison fait référence au lien entre l'appel de méthode et la définition de méthode.

Cette image montre clairement ce qui est contraignant.

contraignant

Dans cette image, l'appel «a1.methodOne ()» est lié à la définition de methodOne () correspondante et l'appel «a1.methodTwo ()» est lié à la définition de methodTwo () correspondante.

Pour chaque appel de méthode, il doit y avoir une définition de méthode appropriée. C'est une règle en java. Si le compilateur ne voit pas la définition de méthode appropriée pour chaque appel de méthode, il renvoie une erreur.

Maintenant, venez à la liaison statique et à la liaison dynamique en java.

Liaison statique en Java:

La liaison statique est une liaison qui se produit lors de la compilation. Il est également appelé liaison anticipée car la liaison se produit avant l'exécution d'un programme

.

La liaison statique peut être démontrée comme dans l'image ci-dessous.

entrez la description de l'image ici

Dans cette image, 'a1' est une variable de référence de type Classe A pointant vers un objet de classe A. 'a2' est également une variable de référence de type classe A mais pointant vers un objet de Classe B.

Pendant la compilation, lors de la liaison, le compilateur ne vérifie pas le type d'objet vers lequel pointe une variable de référence particulière. Il vérifie simplement le type de variable de référence via laquelle une méthode est appelée et vérifie s'il existe une définition de méthode pour elle dans ce type.

Par exemple, pour l'appel de méthode «a1.method ()» dans l'image ci-dessus, le compilateur vérifie s'il existe une définition de méthode pour method () dans la classe A. Parce que 'a1' est de type classe A. De même, pour l'appel de méthode «a2.method ()», il vérifie s'il existe une définition de méthode pour method () dans la classe A. Parce que 'a2' est également de type classe A. Il ne vérifie pas vers quel objet "a1" et "a2" pointent. Ce type de liaison est appelé liaison statique.

Liaison dynamique en Java:

La liaison dynamique est une liaison qui se produit pendant l'exécution. Il est également appelé liaison tardive car la liaison se produit lorsque le programme est en cours d'exécution.

Pendant l'exécution, des objets réels sont utilisés pour la liaison. Par exemple, pour l'appel «a1.method ()» dans l'image ci-dessus, la méthode () de l'objet réel vers lequel pointe «a1» sera appelée. Pour l'appel «a2.method ()», la méthode () de l'objet réel vers lequel pointe «a2» sera appelée. Ce type de liaison est appelé liaison dynamique.

La liaison dynamique de l'exemple ci-dessus peut être démontrée comme ci-dessous.

entrez la description de l'image ici

Référence static-binding-and-dynamic-binding-in-java


mieux qu'avant.
AnBisw

8

Polymorphisme: Le polymorphisme est la capacité d'un objet à prendre de nombreuses formes. L'utilisation la plus courante du polymorphisme dans la POO se produit lorsqu'une référence de classe parent est utilisée pour faire référence à un objet de classe enfant.

Liaison dynamique / Polymorphisme d'exécution:

Polymorphisme à l'exécution, également appelé remplacement de méthode. Dans ce mécanisme par lequel un appel à une fonction remplacée est résolu au moment de l'exécution.

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");
    }
}

Production:

Méthode de démarrage intérieur de la voiture

Liaison statique / polymorphisme à la compilation:

La méthode à appeler est décidée au moment de la compilation uniquement.

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;
    }

}

Sortie: Metho de tri à l'intérieur de la collection


8

la surcharge de méthode est un exemple de polymorphisme statique au moment de la compilation car la liaison de méthode entre l'appel de méthode et la définition de méthode se produit au moment de la compilation et dépend de la référence de la classe (référence créée au moment de la compilation et va à la pile).

le remplacement de méthode est un exemple de polymorphisme dynamique à l'exécution, car la liaison de méthode entre l'appel de méthode et la définition de méthode se produit au moment de l'exécution et dépend de l'objet de la classe (objet créé au moment de l'exécution et va au tas).


* (objet créé au moment de l'exécution et va au tas), il devrait s'exécuter
Rendez-vous

7

En termes simples:

Polymorphisme statique : le même nom de méthode est surchargé avec un type ou un nombre de paramètres différents dans la même classe (signature différente). L'appel de méthode ciblée est résolu au moment de la compilation.

Polymorphisme dynamique : la même méthode est remplacée par la même signature dans différentes classes . Le type d'objet sur lequel la méthode est appelée n'est pas connu au moment de la compilation, mais sera décidé au moment de l'exécution.

En général, la surcharge ne sera pas considérée comme un polymorphisme.

À partir de la page du didacticiel Java :

Les sous-classes d'une classe peuvent définir leurs propres comportements uniques tout en partageant certaines des mêmes fonctionnalités de la classe parente


Generally overloading won't be considered as polymorphism.pouvez-vous s'il vous plaît élaborer sur ce point.
prime

1
La liaison et le dépassement dynamiques sont un point frappant pour le polymorphisme
Ravindra babu

5

La surcharge de méthode est connue sous le nom de polymorphisme statique et également connue sous le nom de polymorphisme au moment de la compilation ou de liaison statique car les appels de méthode surchargés sont résolus au moment de la compilation par le compilateur sur la base de la liste d'arguments et de la référence sur laquelle nous appelons la méthode.

Et méthode redéfinie est connu comme dynamique Polymorphisme simple ou Polymorphisme ou d' exécution Méthode de répartition ou de liaison dynamique parce que l' appel de méthode surchargée se résoudre à l' exécution.

Afin de comprendre pourquoi il en est ainsi, prenons un exemple de Mammalet Humanclasse

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");
    }

}

J'ai inclus la sortie ainsi que le bytecode dans les lignes de code ci-dessous

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

Et en regardant le code ci-dessus, nous pouvons voir que les bytecodes de humanMammal.speak (), human.speak () et human.speak ("Hindi") sont totalement différents car le compilateur est capable de les différencier en fonction de la liste d'arguments et référence de classe. Et c'est pourquoi la surcharge de méthode est connue sous le nom de polymorphisme statique .

Mais le bytecode pour anyMammal.speak () et humanMammal.speak () est le même car, selon le compilateur, les deux méthodes sont appelées sur la référence Mammal, mais la sortie des deux appels de méthode est différente car au moment de l'exécution, la JVM sait quel objet une référence contient et les appels JVM. la méthode sur l'objet et c'est pourquoi le remplacement de méthode est connu sous le nom de polymorphisme dynamique.

Ainsi, à partir du code et du bytecode ci-dessus, il est clair que pendant la phase de compilation, la méthode d'appel est considérée à partir du type de référence. Mais au moment de l'exécution, la méthode sera appelée à partir de l'objet que contient la référence.

Si vous voulez en savoir plus à ce sujet, vous pouvez en savoir plus sur la manière dont la JVM gère la surcharge et le remplacement de méthode en interne .


3

Polymorphisme statique: c'est là que la décision de résoudre la méthode à accomplir est déterminée pendant la compilation. La surcharge de méthode pourrait en être un exemple.

Polymorphisme dynamique: c'est là que la décision de choisir la méthode à exécuter est définie pendant l'exécution. Le remplacement de méthode pourrait en être un exemple.


3

Le polymorphisme fait référence à la capacité d'un objet à se comporter différemment pour le même déclencheur.

Polymorphisme statique (polymorphisme à la compilation)

  • Le polymorphisme statique décide de la méthode à exécuter pendant la compilation.
  • La surcharge de méthode est un exemple de polymorphisme statique, et il est nécessaire de se produire un polymorphisme statique.
  • Polymorphisme statique obtenu par liaison statique.
  • Le polymorphisme statique se produit dans la même classe.
  • L'affectation d'objet n'est pas requise pour le polymorphisme statique.
  • Héritage non impliqué pour le polymorphisme statique.

Polymorphisme dynamique (polymorphisme d'exécution)

  • Le polymorphisme dynamique décide de la méthode à exécuter lors de l'exécution.
  • Le remplacement de méthode est un exemple de polymorphisme dynamique, et il est nécessaire qu'il se produise un polymorphisme dynamique.
  • Polymorphisme dynamique obtenu grâce à la liaison dynamique.
  • Le polymorphisme dynamique se produit entre différentes classes.
  • Il est requis lorsqu'un objet de sous-classe est affecté à un objet de super classe pour le polymorphisme dynamique.
  • Héritage impliqué pour le polymorphisme dynamique.

1

Polymorphisme au moment de la compilation (liaison statique / liaison précoce): Dans le polymorphisme statique, si nous appelons une méthode dans notre code, la définition de cette méthode qui doit être appelée est résolue au moment de la compilation uniquement.

(ou)

Au moment de la compilation, Java sait quelle méthode appeler en vérifiant les signatures de méthode. Donc, cela s'appelle le polymorphisme à la compilation ou la liaison statique.

Polymorphisme dynamique (Late Binding / Runtime Polymorphism): Au moment de l'exécution, Java attend l'exécution pour déterminer quel objet est réellement pointé par la référence. La résolution de la méthode a été prise au moment de l'exécution, c'est pourquoi nous appelons le polymorphisme d'exécution.


1

Considérez le code ci-dessous:

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();
}
}

Maintenant, en regardant le code, vous ne pouvez jamais dire quelle implémentation de methodA () sera exécutée, car cela dépend de la valeur que l'utilisateur donne pendant l'exécution. Ainsi, il n'est décidé que pendant l'exécution de la méthode qui sera appelée. Par conséquent, le polymorphisme d'exécution.


0

La surcharge de méthode est un polymorphisme au moment de la compilation, prenons un exemple pour comprendre le concept.

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
  {

  }

}

Dans cet exemple, Person a une méthode eat qui signifie qu'il peut manger de la pizza ou des nouilles. Que la méthode eat est surchargée lorsque nous compilons ce Person.java le compilateur résout l'appel de méthode "e.eat (noodles) [qui est à la ligne 6] avec la définition de méthode spécifiée à la ligne 8, c'est-à-dire la méthode qui prend les noodles comme paramètre et le processus entier est fait par le compilateur donc c'est Polymorphisme au moment de la compilation. Le processus de remplacement de l'appel de méthode par la définition de méthode est appelé comme liaison, dans ce cas, il est fait par le compilateur donc il est appelé comme liaison précoce.


0

Suite à la réponse de Naresh, le polymorphisme dynamique n'est «dynamique» qu'en Java en raison de la présence de la machine virtuelle et de sa capacité à interpréter le code au moment de l'exécution plutôt que le code s'exécutant en natif.

En C ++, il doit être résolu au moment de la compilation s'il est compilé dans un binaire natif en utilisant gcc, évidemment; cependant, le saut et le bruit à l'exécution dans la table virtuelle sont toujours appelés «recherche» ou «dynamique». Si C hérite de B, et que vous déclarez B* b = new C(); b->method1();, b sera résolu par le compilateur pour pointer vers un objet B à l'intérieur de C (pour une classe simple hérite d'une situation de classe, l'objet B à l'intérieur de C et C démarrera à la même adresse mémoire donc rien doit être fait; il pointera vers le vptr qu'ils utilisent tous les deux). Si C hérite de B et A, la table des fonctions virtuelles de l'objet A à l'intérieur de l'entrée C pour method1 aura un thunk qui décalera le pointeur vers le début de l'objet C encapsulant puis le passera au réel A :: method1 () dans le segment de texte que C a remplacé. PourC* c = new C(); c->method1(), c pointera déjà vers l'objet C externe et le pointeur sera passé à C :: method1 () dans le segment de texte. Reportez-vous à: http://www.programmersought.com/article/2572545946/

En java, pour B b = new C(); b.method1();, la machine virtuelle est capable de vérifier dynamiquement le type de l'objet associé à b et peut passer le bon pointeur et appeler la bonne méthode. L'étape supplémentaire de la machine virtuelle élimine le besoin de tables de fonctions virtuelles ou du type en cours de résolution au moment de la compilation, même s'il pouvait être connu au moment de la compilation. C'est juste une façon différente de le faire, ce qui a du sens lorsqu'une machine virtuelle est impliquée et que le code n'est compilé qu'en bytecode.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.