Thématiques principales

jeudi 19 octobre 2017

Polymorphisme

Nous allons abordé une question très conceptuelle aujourd'hui : le polymorphisme.... Tout d'abord, pourquoi aborder ce sujet? En fait, a l'occasion d'un entretien de recrutement, j'ai eu cette désagréable question : "Qu'est ce que le polymorphisme?" Et j'avoue que j'ai été vraiment surpris et voila ce qui est passé par ma tête:
  • Quoi? On me pose cette question ? A quel moment j'ai réussi a laisser entendre que j’étais aussi nul que ça?
  • Hein?, c'est l’héritage quoi.... euh attend non ca se résume pas qu'a ca....
  • Merde c'est vraiment que ça le polymorphisme?
Bon passons sur le problème de l'ego... après tout je n’écrirais pas cet article si je n’étais pas prêt a me remettre en question...

Alors avant que tout le monde ne cri, je veux d'abord distinguer le concept de son implémentation. En effet le polymorphisme signifie: "qui a plusieurs formes...." Et la on est bien avancé. Cependant il est a noté que c'est bien ce que dit conceptuellement la définition. Alors mais qu'est ce qui peut avoir plusieurs formes? et bien l'objet, celui de la programmation orienté objet.

Je ne vais pas entrer dans le détail des différentes type de programmation mais il faut savoir qu'initialement la programmation est né sous la forme impérative, c'est a dire que l'on exécuter séquentiellement des listes d’instructions, puis face a la redondance des listings on s'est mis a créer des procédures et des fonctions nous amenant  a la programmation procédurale que nous avons fini par regrouper dans des modules afin de les classer et les cataloguer arrivant ainsi aux bibliothèques de fonctions.

L'objet est né à la suite de la programmation modulaire ou le besoin conceptuel d’étendre les fonctionnalités d'un module et de consolider un certain nombre de données propres au module s'est fait sentir et ce en fonction du contexte d'utilisation du module en question. Ainsi à partir d'un module de base, nous avons fait dérivé plusieurs modules ayant des objectifs différents et donc des fonctions complémentaires.

Donc un objet c'est:

  • une référence, ce qui va nous permettre de le manipuler, donc son adresse mémoire ou un pointeur vers celui ci, sans la référence, l'objet sera considérer comme susceptible d’être supprimé
  • un comportement, un ensemble de fonction accessible via la référence et permettant de faire évoluer son état
  • un état, ensemble de données traduisant de l'activité de l'objet dans le temps. 
En POO vont intervenir 4 concepts clefs :

  • la surcharge qui ne nous intéresse pas vraiment ici mais qui consiste a créer des fonctions portant le même nom mais avec des signatures différents
  • l’héritage permet a deux objets de disposer d'une relation de parenté qui donne a l'un la possibilité d'utiliser les fonction de l'autre
  • la redéfinition permet a un objet de reprendre complètement la signature d'une fonction de sa classe mère pour en re caractériser le comportement
  • le polymorphisme permet a l’exécution de faire le choix selon la nature réelle de l'objet a exécuter ses fonctions redéfinies ou non.

Donc voila ce qu'est le polymorphisme, illustrons le. Prenons un exemple simple en considérant deux objets A et B:

A défini la fonction toto.
B dérive A. (donc B connait toto)
B défini la fonction tata utilisant toto
B redéfini toto car celle ci ne fourni pas un comportement complet dans son cas d'utilisation.
Que se passera-t-il lorsque B appellera tata?
  • a) tata appellera toto de B
  • b) tata appellera toto de A
  • c) on sait pas
  • d) la réponse d
Bon c'est la réponse c car effectivement on a effectuer une redéfinition mais sans une définition du polymorphisme on ne peut prédire le comportement. Donc dans tata il faudra trouver quelques chose comme "B.toto" si on veut être sur du comportement. Mais si on fait une liste de A dans laquelle on place un B sous la forme d'un A et que l'on appelle itérativement toto, lorsque l'on sera sur le B, on appellera quelle définition de toto? et bien retour a la réponse c, car dans notre car si on aimerai bien appeler celle de B il y a des chance que ce soit plutôt celle de A.

Et donc le polymorphisme c'est ca, obliger l’exécution du toto de B lorsque l'on a un B même si en façade on ne voit qu'un A. Attention, ici je ne parle encore que conceptuellement et n'introduit pas l'implantation de ces concepts dans tel ou tel langage ... on va y venir.

Donc pour préciser le polymorphisme il faudrait fonction après fonction dire si une redéfinition peut être polymorphique ou non. On va donc s'aider d'un mot clef, on va prendre par pur hasard le mot clef virtual. Ainsi voici deux exemples d’utilisations:

Exemple 1 équivalent a l'exemple précèdent (on prendra -> pour défini, et les parenthèses pour dérive)
A -> toto
B(A) -> toto

Exemple 2
A -> virtual toto
B(A) -> virtual toto

Ainsi si on prend un B pour a A est que l'on appelle toto, alors :
  •  dans l'exemple 1 on appellera le toto de A.
  •  dans l'exemple 2 on appellera le toto de B 
Bingo, avec l'exemple 2 on a un comportement polymorphique car si on considère un C dérivant de A redéfinissant lui aussi (ou non d’ailleurs) la fonction toto, alors sur la liste de A incluant un A un B et un C, on aura 3 appels de toto différents alors que l'on manipule que des A... plusieurs comportements, plusieurs formes : polymorphisme!

Jusqu'ici on a pas parler de langages de programmation. Pourquoi? parce que le polymorphisme ne doit pas se définir au travers d'un langage. Il ne faut pas oublier que l'on parle juste d'objets ayant différentes formes. Et on peut voir des différences notables selon les langages:
  • Le C++ sait utiliser les deux cas des exemples 1 et 2. Il faut donc préciser si l'on souhaite que la redéfinition soit polymorphique ou non.
  • Par contre en java ou python, on sera forcement dans l'exemple 2 (la redéfinition est forcement polymorphique). 
Alors le polymorphisme, c'est quoi? et bien effectivement c'est intimement lié a l’héritage surtout dans l’implémentation que l'on en a aujourd'hui. Cela dit (et je reviens a l'entretien qui j'ai eu) certain chipoterons sur les différents types en parlant par exemple des interfaces Java.... Aie, effectivement, l’héritage par les interfaces java oblige la redéfinition donc par extension oblige à la mise en œuvre du polymorphisme... mais conceptuellement, c'est la même chose que de définir une classe abstraite (ou virtuelle pure en c++). Nous sommes la juste dans un contexte d’implémentation du concept de polymorphisme, pas du tout dans ce qu'il est, juste une caractéristique possible de la redéfinition de fonction.

Rappelons au passage que l’existence des interfaces Java ne provient que du besoin de permettre des héritages multiples (comme en c++ ou python) mais en limitant les effets de bords liés a l’héritage en diamant.... et que l'utilisation des interfaces est essentiellement préconisé pour l'adjonction de fonctionnalités techniques sur un objet (capacité a se sérialiser par exemple) et non pour la définition de spécificité naturelle a l'objet (la capacité d'avancer....).

Pour ceux qui veulent des infos rapides: Openclassrooms
Sinon pour les courageux : Amazon
Pour ceux qui veulent comprendre plus en profondeur : SiscoLaf

Aucun commentaire:

Enregistrer un commentaire