Essayez de décrire le polymorphism aussi facilement que possible

Comment le polymorphism peut-il être décrit d’une manière facile à comprendre?

Nous pouvons trouver beaucoup d’informations sur le sujet sur Internet et les livres, comme dans le polymorphism de type . Mais essayons de le rendre aussi simple que possible.

C’est à partir de ma réponse d’une question similaire. Voici un exemple de polymorphism en pseudo-C # / Java:

class Animal { abstract ssortingng MakeNoise (); } class Cat : Animal { ssortingng MakeNoise () { return "Meow"; } } class Dog : Animal { ssortingng MakeNoise () { return "Bark"; } } Main () { Animal animal = Zoo.GetAnimal (); Console.WriteLine (animal.MakeNoise ()); } 

La méthode Main () ne connaît pas le type de l’animal et dépend du comportement d’une implémentation particulière de la méthode MakeNoise ().

Deux objects répondent au même message avec des comportements différents; l’expéditeur n’a pas à s’en soucier.

Chaque boîte avec un simple couvercle pop s’ouvre de la même manière.
En tant qu’être humain, vous savez que vous pouvez ouvrir n’importe quoi.

Une fois ouvertes, toutes les boîtes ne se comportent pas de la même manière.
Certains contiennent des noix, certains contiennent de faux serpents qui sortent.
Le résultat dépend de quel type de canette, si la canette était un “CanOfNuts” ou un “CanOfSnakes”, mais cela n’a aucune incidence sur COMMENT vous l’ouvrez. Vous savez juste que vous pouvez ouvrir n’importe quel Can, et vous obtiendrez une sorte de résultat décidé en fonction du type de Can que vous avez ouvert.

pUnlabledCan-> Open (); // pourrait donner des noix, pourrait donner des serpents. Nous ne soaps pas jusqu’à ce que nous l’appelions

Open () a un type de retour générique de “Contents” (ou nous pourrions décider de ne pas retourner de type), de sorte que open a toujours la même signature de fonction.

Vous, l’humain, êtes l’utilisateur / l’appelant.
Open () est la fonction virtuelle / polymorphe.
“Can” est la classe de base abstraite.
CanOfNuts et CanOfSnakes sont les enfants polymorphes de la classe “Can”.
Chaque boîte peut être ouverte, mais en quoi consiste-t-elle spécifiquement et quel type de contenu spécifique elle retourne?
Tout ce que vous savez quand vous voyez pUnlabledCan, c’est que vous pouvez l’ouvrir (), et cela renverra le contenu. Tous les autres comportements (tels que les éclats de serpents dans votre visage) sont décidés par le Can.

La description la plus simple du polymorphism est que c’est un moyen de réduire les instructions if / switch .

Il a également l’avantage de vous permettre d’étendre vos instructions if / switch (ou celles d’autres personnes) sans modifier les classes existantes.

Par exemple, considérez la classe Stream dans .NET. Sans polymorphism, il s’agirait d’une classe massive unique dans laquelle chaque méthode implémenterait une instruction switch telle que:

 public class Stream { public int Read(byte[] buffer, int offset, int count) { if (this.mode == "file") { // behave like a file stream } else if (this.mode == "network") { // behave like a network stream } else // etc. } } 

Au lieu de cela, nous autorisons le moteur d’exécution à effectuer la commutation de manière plus efficace, en choisissant automatiquement l’implémentation en fonction du type concret ( FileStream , NetworkStream ), par exemple

 public class FileStream : Stream { public override int Read(byte[] buffer, int offset, int count) { // behave like a file stream } } public class NetworkStream : Stream { public override int Read(byte[] buffer, int offset, int count) { // behave like a network stream } } 

Poly: beaucoup
Morphisme: formes / formes

L’acteur par rapport au personnage (ou rôle)

Les pommes et les oranges sont les deux fruits. Les fruits peuvent être consommés. Par conséquent, les pommes et les oranges peuvent être consommées.

Le kicker? Vous les mangez différemment! Vous épluchez les oranges, mais pas les pommes.

Donc, la mise en œuvre diffère, mais le résultat final est le même, vous mangez le fruit .

Si vous marchez comme un canard et que les charlatans comme un canard, vous pouvez le traiter comme un canard partout où vous avez besoin d’un canard.

Ceci est un meilleur article en fait

Le polymorphism permet aux objects de “regarder” de la même manière, mais se comporte de différentes manières. L’exemple habituel est de prendre une classe de base animale avec une méthode Speak (). Une sous-classe de chien émettrait une Bark alors qu’une sous-classe de Pig émettrait un oink.

La réponse courte de 5 secondes que la plupart des gens utilisent pour que les autres développeurs puissent se faire une idée

Même syntaxe, sémantique différente.

Manière la plus simple de le décrire: un verbe qui peut s’appliquer à plus d’un type d’object.

Comme le dit Hillel, tout le rest n’est que commentaire.

Le polymorphism consiste à traiter les choses de façon abstraite en s’appuyant sur la connaissance d’un «parent» commun (pensez aux inheritances comme Animal en tant que parent de chiens et de chats).

Par exemple, tous les animaux peuvent respirer de l’oxygène et, bien que chacun puisse le faire différemment, vous pourriez concevoir une installation fournissant de l’oxygène pour que les animaux respirent, soutenant à la fois les chiens et les chats.

Comme un petit plus, vous pouvez le faire même si Animal est un identifiant “abstrait” (il n’y a pas de véritable “animal”, juste des types d’animaux).

Le polymorphism est le stockage de valeurs de plusieurs types dans un emplacement d’un type unique.

Notez que la plupart des autres réponses à cette question, au moment de mon écriture, décrivent en fait la répartition dynamic, pas le polymorphism.

L’envoi dynamic nécessite un polymorphism, mais l’inverse n’est pas vrai. On pourrait imaginer un langage très similaire à Java ou C # mais dont System.Object n’a aucun membre; le typage serait nécessaire avant de faire quoi que ce soit avec la valeur. Dans ce langage notionnel, il y aurait un polymorphism, mais pas nécessairement des méthodes virtuelles, ou tout autre mécanisme de répartition dynamic.

L’envoi dynamic est le concept connexe mais distinct, assez bien décrit dans la plupart des autres réponses. Cependant, la manière dont cela fonctionne normalement dans les langages orientés object (sélectionner une fonction basée sur le premier type d’argument «this» ou «Self») n’est pas la seule façon de fonctionner. L’envoi multiple est également possible, où la sélection est appliquée à tous les types d’arguments.

De même, la résolution des surcharges et les envois multiples sont des analogues exacts les uns des autres; la résolution de surcharge est une répartition multiple appliquée aux types statiques, tandis que la dissortingbution multiple est une résolution de surcharge appliquée aux types d’exécution stockés dans des emplacements polymorphes.

Le polymorphism consiste à diviser le monde en boîtes basées sur des propriétés communes et à traiter les éléments d’une boîte donnée comme étant interchangeables lorsque vous souhaitez uniquement utiliser ces propriétés communes.

Le polymorphism est la capacité à traiter différentes choses comme si elles étaient la même chose en établissant une identité partagée entre elles, puis en les exploitant.

Le polymorphism est ce que vous obtenez lorsque la même méthode s’applique à plusieurs classes. Par exemple, une chaîne et une liste peuvent avoir des méthodes “inversées”. Les deux méthodes ont le même nom (“Reverse”). Les deux méthodes font quelque chose de très similaire (inverser tous les caractères ou inverser l’ordre des éléments dans la liste). Mais la mise en œuvre de chaque méthode “Reverse” est différente et spécifique à sa classe. (En d’autres termes, la chaîne s’inverse comme une chaîne et la liste s’inverse comme une liste.)

Pour utiliser une métaphore, vous pourriez dire “Make Dinner” à un chef français ou à un chef japonais. Chacun effectuerait “faire le dîner” de manière caractéristique.

Le résultat pratique est que vous pouvez créer un “moteur d’inversion” qui accepte un object et appelle “Reverse” dessus. Tant que l’object possède une méthode Reverse, votre moteur de réversion fonctionnera.

Pour prolonger l’analogie du chef, vous pouvez créer un “Waiterbot” qui indique aux chefs de “préparer le dîner”. Le Waiterbot n’a pas besoin de savoir quel type de dîner va être fait. Il ne faut même pas s’assurer qu’il parle à un chef. Tout ce qui compte, c’est que le «chef» (ou le pompier, le dissortingbuteur automatique ou le dissortingbuteur d’aliments pour animaux) sache quoi faire quand on lui dit de «préparer le dîner».

Ce que cela vous achète en tant que programmeur, c’est moins de lignes de code et de sécurité de type ou de liaison tardive. Par exemple, voici un exemple de sécurité de type et de liaison anticipée (dans un langage c-like que je rattrape au fur et à mesure):

 class BankAccount { void SubtractMonthlyFee } class CheckingAccount : BankAccount {} class SavingsAccount : BankAccount {} AssessFee(BankAccount acct) { // This will work for any class derived from // BankAccount; even classes that don't exist yet acct.SubtractMonthlyFee } main() { CheckingAccount chkAcct; SavingsAccount saveAcct; // both lines will comstack, because both accounts // derive from "BankAccount". If you try to pass in // an object that doesn't, it won't comstack, EVEN // if the object has a "SubtractMonthlyFee" method. AssessFee(chkAcct); AssessFee(saveAcct); } 

Voici un exemple sans sécurité de type mais avec liaison tardive:

 class DatabaseConnection { void ReleaseResources } class FileHandle { void ReleaseResources } FreeMemory(Object obj) { // This will work for any class that has a // "ReleaseResources" method (assuming all // classes are ultimately derived from Object. obj.ReleaseResources } main() { DatabaseConnection dbConn; FileHandle fh; // You can pass in anything at all and it will // comstack just fine. But if you pass in an // object that doesn't have a "ReleaseResources" // method you'll get a run-time error. FreeMemory(dbConn); FreeMemory(fh); FreeMemory(acct); //FAIL! (but not until run-time) } 

Pour un excellent exemple, consultez la méthode .NET ToSsortingng (). Toutes les classes l’ont parce que toutes les classes sont dérivées de la classe Object. Mais chaque classe peut implémenter ToSsortingng () d’une manière qui lui soit propre.

EDIT: Simple! = Court, à mon humble avis

Le polymorphism est une fonctionnalité du langage permettant au code algorithmique de haut niveau de fonctionner sans modification sur plusieurs types de données.

Cela se fait en veillant à ce que les opérations invoquent la bonne implémentation pour chaque type de données. Même dans un contexte de POO (selon l’étiquette de cette question), cette “implémentation correcte” peut être résolue à la compilation ou à l’exécution (si votre langue prend en charge les deux). Dans certains langages comme C ++, la prise en charge du polymorphism au moment de l’exécution (c’est-à-dire la répartition virtuelle) fournie par le compilateur est spécifique à la POO, alors que d’autres types de polymorphism peuvent également fonctionner sur des types de données non peut être des types intégrés comme int ou double ).

(Les types de polymorphisms pris en charge par C ++ sont listés et contrastés dans ma réponse: Polymorphisme en c ++ – même si vous programmez d’autres langages, il est potentiellement instructif)

La façon dont j’essaie d’y penser est quelque chose qui ressemble à la même chose mais qui peut avoir des fonctionnalités différentes selon l’instance. Vous pouvez donc avoir un type

 interface IJobLoader 

mais selon la manière dont il est utilisé, il peut avoir différentes fonctionnalités tout en restant identique. Vous pouvez avoir des instances pour BatchJobLoader, NightlyJobLoader, etc.

Peut-être que je suis loin.

Le terme polymorphism peut également s’appliquer aux fonctions de surcharge. Par exemple,

 ssortingng MyFunc(ClassA anA); ssortingng MyFunc(ClassB aB); 

est un exemple de polymorphism non orienté object.

Est-ce la capacité que les objects doivent répondre au même message de différentes manières.

Par exemple, dans des langages tels que smalltalk, Ruby, Objective-C, il suffit d’envoyer le message et ils répondront.

  dao = XmlDao.createNewInstance() #obj 1 dao.save( data ) dao = RdbDao.createNewnewInstance() #obj 2 dao.save( data ) 

Dans cet exemple, deux objects différents ont répondu de différentes manières aux mêmes messages: “createNewInstance () et save (obj)”

Ils agissent de différentes manières, sur le même message. Dans les langues ci-dessus, les classes ne sont peut-être même pas dans la même hiérarchie de classes, il suffit qu’elles répondent au message.

Dans des langages tels que Java, C ++, C #, etc. Pour assigner l’object à une référence d’object, ils doivent partager la même hiérarchie de type en implémentant l’interface ou en étant sous-classe d’une classe commune.

facile .. et simple.

Le polymorphism est de loin la caractéristique la plus importante et la plus pertinente de la programmation orientée object.

C’est une façon de traiter différentes choses qui peuvent faire quelque chose de similaire de la même manière sans se soucier de la façon dont elles le font.

Disons que vous avez un jeu avec un tas de différents types de véhicules circulant comme une voiture, un camion, une planche à roulettes, un avion, etc. Ils peuvent tous s’arrêter, mais chaque véhicule s’arrête d’une manière différente. Certains véhicules peuvent avoir besoin de réduire leur vitesse et d’autres peuvent arriver à un arrêt à froid. Le polymophisme vous permet de le faire

 foreach (Vehicle v in Game.Vehicles) { v.Stop(); } 

La façon dont cet arrêt est mis en œuvre est rescope sur les différents véhicules, de sorte que votre programme n’en a pas besoin.

C’est juste un moyen d’obtenir du vieux froid d’appeler un nouveau code. Vous écrivez une application qui accepte une interface “Shape” avec des méthodes que d’autres doivent implémenter (exemple – getArea). Si quelqu’un propose une nouvelle méthode pour implémenter cette interface, votre ancien code peut appeler ce nouveau code via la méthode getArea.

L’aptitude d’un object (par exemple une voiture) à agir (par exemple, un frein) comme un autre type (par exemple un véhicule) qui suggère généralement une ascendance commune (par exemple, une voiture est un sous-type de véhicule) .

Le polymorphism est la solution orientée object permettant de transmettre une fonction à une autre fonction. En C tu peux faire

  void h() { float x=3.0; printf("%f", x); } void k() { int y=5; printf("%i", y); } void g(void (*f)()) { f(); } g(h); // output 3.0 g(k); // output 5 

En C, les choses se compliquent si la fonction dépend de parameters supplémentaires. Si les fonctions h et k dépendent de différents types de parameters, vous êtes en difficulté et vous devez utiliser le casting. Vous devez stocker ces parameters dans une structure de données et transmettre un pointeur à cette structure de données à g qui le transmet à h ou k. h et k jettent le pointeur dans un pointeur sur la structure appropriée et décompressent les données. Très en désordre et très dangereux à cause des erreurs de lancement possibles:

  void h(void *a) { float* x=(float*)a; printf("%f",*x); } void k(void *a) { int* y=(int*)a; printf("%i",*y); } void g(void (*f)(void *a),void *a) { f(a); } float x=3.0; int y=5; g(h,&x); // output x g(k,&y); // output y 

Ils ont donc inventé le polymorphism. h et k sont promus en classes et les fonctions réelles en méthodes, les parameters sont des variables membres de la classe respective, h ou k. Au lieu de passer la fonction, vous passez une instance de la classe contenant la fonction souhaitée. L’instance contient ses propres parameters.

 class Base { virtual public void call()=0; } class H : public Base { float x; public void call() { printf("%f",x);} } h; class K : public Base { int y; public void call() { printf("%i",y);} } k; void g(Base &f) { f.call(); }; hx=3.0; ky=5; g(h); // output hx g(k); // output kx