{"id":73,"date":"2021-05-29T14:00:01","date_gmt":"2021-05-29T14:00:01","guid":{"rendered":"https:\/\/www.louismarchand.me\/?page_id=73"},"modified":"2021-05-29T14:22:17","modified_gmt":"2021-05-29T14:22:17","slug":"polymorphisme","status":"publish","type":"page","link":"https:\/\/www.louismarchand.me\/index.php\/polymorphisme\/","title":{"rendered":"Polymorphisme"},"content":{"rendered":"<h2>Introduction<\/h2>\n<p>La programmation orient\u00e9e objet permet plusieurs avantages majeurs au niveau du code. Nous avons d\u00e9j\u00e0 vu que dans les avantages de ce paradigme, il y a la repr\u00e9sentation plus intuitive de la programmation en repr\u00e9sentant les structures en se basant sur des \u00e9l\u00e9ments r\u00e9els (Produit, Animal, Personnes, etc.) au lieu de se baser sur des structures abstraites de donn\u00e9e (Tableau, Liste, Arbre, etc.) Un autre avantage est de faciliter la r\u00e9utilisation de code, ce qui pr\u00e9sente une multitude d&rsquo;avantages(diminution de la duplication de code, facilite la maintenance, etc.)<\/p>\n<p>Un autre des avantages de la programmation orient\u00e9e objet est la possibilit\u00e9 d&rsquo;utiliser du polymorphisme. Gr\u00e2ce \u00e0 cette m\u00e9canique, il est possible de g\u00e9n\u00e9raliser le code de mani\u00e8re \u00e0 g\u00e9rer une grande quantit\u00e9 d&rsquo;objets d&rsquo;un m\u00eame coup. Encore une fois, cette m\u00e9canique permet plusieurs avantages, tels qu&rsquo;avoir du code plus logique, encore diminuer la duplication de code ainsi que faciliter la maintenance du logiciel.<\/p>\n<h2>Qu&rsquo;est-ce que le polymorphisme<\/h2>\n<p>On dit qu&rsquo;une assignation (incluant le passage d&rsquo;argument) est <strong>polymorphique<\/strong> dans le cas ou le type de l&rsquo;expression source est diff\u00e9rent du type de la cible de l&rsquo;assignation.<\/p>\n<p>On appelle <strong>polymorphisme<\/strong> la m\u00e9canique permettant \u00e0 une assignation d&rsquo;\u00eatre polymorphique.<\/p>\n<p>Cette description peut para\u00eetre \u00e9trange \u00e0 premi\u00e8re vue, mais je vais pr\u00e9ciser par un exemple. Pour pr\u00e9senter l&rsquo;exemple, je vais utiliser l&rsquo;arbre d&rsquo;h\u00e9ritage suivant:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-10057 size-full\" src=\"https:\/\/www.louismarchand.me\/wp-content\/uploads\/2021\/05\/animal-1.png\" alt=\"\" width=\"354\" height=\"305\"><\/p>\n<p>Donc, soit le code suivant:<\/p>\n<pre>new Chien()<\/pre>\n<p>Nous voyons que cette expression cr\u00e9e une instance de type \u00ab\u00a0Chien\u00a0\u00bb.<\/p>\n<p>Maintenant, prenons la d\u00e9claration:<\/p>\n<pre>Animal monAnimal<\/pre>\n<p>On voit que la variable \u00ab\u00a0monAnimal\u00a0\u00bb est de type \u00ab\u00a0Animal\u00a0\u00bb.<\/p>\n<p>Maintenant, prenons l&rsquo;assignation suivante:<\/p>\n<pre>Animal monAnimal = new Chien();<\/pre>\n<p>Cette assignation est valide puis que si \u00ab\u00a0Chien\u00a0\u00bb h\u00e9rite d\u2019Animal, on a que \u00ab\u00a0Chien\u00a0\u00bb est un \u00ab\u00a0Animal\u00a0\u00bb. Et si \u00ab\u00a0Chien\u00a0\u00bb est un \u00ab\u00a0Animal\u00a0\u00bb, donc un objet de type \u00ab\u00a0Chien\u00a0\u00bb peut \u00eatre assign\u00e9 \u00e0 une variable de type \u00ab\u00a0Animal\u00a0\u00bb (comme dans cet exemple).<\/p>\n<p>Comme dit plus haut, un passage d&rsquo;argument peut \u00e9galement \u00eatre polymorphique. Si je prend, par exemple le code suivant:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"cm\">\/**<\/span>\n<span class=\"cm\"> * Appel un animal par son nom.<\/span>\n<span class=\"cm\"> *<\/span>\n<span class=\"cm\"> * @param aAnimal L'Animal \u00e0 appeler<\/span>\n<span class=\"cm\"> **\/<\/span>\n<span class=\"kd\">public<\/span> <span class=\"kt\">void<\/span> <span class=\"nf\">appelerAnimal<\/span><span class=\"o\">(<\/span><span class=\"n\">Animal<\/span> <span class=\"n\">aAnimal<\/span><span class=\"o\">)<\/span>  <span class=\"o\">{<\/span>\n    <span class=\"n\">System<\/span><span class=\"o\">.<\/span><span class=\"na\">out<\/span><span class=\"o\">.<\/span><span class=\"na\">println<\/span><span class=\"o\">(<\/span><span class=\"s\">\"Vient ici \"<\/span> <span class=\"o\">+<\/span> <span class=\"n\">aAnimal<\/span><span class=\"o\">.<\/span><span class=\"na\">getNom<\/span><span class=\"o\">());<\/span>\n<span class=\"o\">}<\/span>\n<\/pre>\n<\/div>\n<p>Donc, le passage d&rsquo;argument suivant est polymorphique:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"n\">Chien<\/span> <span class=\"n\">lChien<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"n\">Chien<\/span><span class=\"o\">(<\/span><span class=\"s\">\"Fido\"<\/span><span class=\"o\">);<\/span>\n<span class=\"n\">appelerAnimal<\/span><span class=\"o\">(<\/span><span class=\"n\">lChien<\/span><span class=\"o\">);<\/span>  <span class=\"c1\">\/\/ Passage d'argument polymorphique<\/span>\n<\/pre>\n<\/div>\n<h2>\u00c0 noter<\/h2>\n<p>Voici certaines informations qu&rsquo;il est pertinent de prendre en compte \u00e0 propos du concept de polymorphisme.<\/p>\n<ul>\n<li>Lorsqu&rsquo;un objet peut \u00eatre assign\u00e9 \u00e0 une variable, on dit que le type de l&rsquo;objet est <strong>conforme<\/strong> au type de la variable.<\/li>\n<li>En programmation orient\u00e9e objet, un type A est conforme \u00e0 un type B si et seulement si A est un descendant de B.<\/li>\n<li>La relation polymorphique n&rsquo;est pas commutative. En d&rsquo;autres mots, si, dans l&rsquo;exemple pr\u00e9c\u00e9dent, on voit que le type \u00ab\u00a0Chien\u00a0\u00bb est conforme au type \u00ab\u00a0Animal\u00a0\u00bb, mais il est inexact de dire que le type \u00ab\u00a0Animal\u00a0\u00bb est conforme au type \u00ab\u00a0Chien\u00a0\u00bb. Donc, l&rsquo;expression suivante est ill\u00e9gale:\n<pre>Chien monChien = new Animal();<\/pre>\n<\/li>\n<li>Le polymorphisme n&rsquo;est pas une conversion. Malgr\u00e9 qu&rsquo;objet est assign\u00e9 \u00e0 une variable d&rsquo;un certain type, le type de l&rsquo;objet ne change pas.<\/li>\n<li>Le polymorphisme peut \u00e9galement \u00eatre utilis\u00e9 comme type g\u00e9n\u00e9rique d&rsquo;une collection (comme une liste par exemple). Voici un exemple:\n<div class=\"highlight\">\n<pre><span class=\"n\">List<\/span><span class=\"o\">&lt;<\/span><span class=\"n\">Animal<\/span><span class=\"o\">&gt;<\/span> <span class=\"n\">maListe<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"n\">ArrayList<\/span><span class=\"o\">&lt;<\/span><span class=\"n\">Animal<\/span><span class=\"o\">&gt;(<\/span><span class=\"mi\">5<\/span><span class=\"o\">);<\/span>\n<span class=\"n\">maListe<\/span><span class=\"o\">.<\/span><span class=\"na\">add<\/span><span class=\"o\">(<\/span><span class=\"k\">new<\/span> <span class=\"n\">Chien<\/span><span class=\"o\">(<\/span><span class=\"s\">\"Fido\"<\/span><span class=\"o\">));<\/span>\n<span class=\"n\">maListe<\/span><span class=\"o\">.<\/span><span class=\"na\">add<\/span><span class=\"o\">(<\/span><span class=\"k\">new<\/span> <span class=\"n\">Chat<\/span><span class=\"o\">(<\/span><span class=\"s\">\"Minou\"<\/span><span class=\"o\">));<\/span>\n<span class=\"n\">maListe<\/span><span class=\"o\">.<\/span><span class=\"na\">add<\/span><span class=\"o\">(<\/span><span class=\"k\">new<\/span> <span class=\"n\">Chien<\/span><span class=\"o\">(<\/span><span class=\"s\">\"Rex\"<\/span><span class=\"o\">));<\/span>\n<span class=\"n\">maListe<\/span><span class=\"o\">.<\/span><span class=\"na\">add<\/span><span class=\"o\">(<\/span><span class=\"k\">new<\/span> <span class=\"n\">Chat<\/span><span class=\"o\">(<\/span><span class=\"s\">\"Minet\"<\/span><span class=\"o\">));<\/span>\n<span class=\"n\">maListe<\/span><span class=\"o\">.<\/span><span class=\"na\">add<\/span><span class=\"o\">(<\/span><span class=\"k\">new<\/span> <span class=\"n\">Chien<\/span><span class=\"o\">(<\/span><span class=\"s\">\"Bull\"<\/span><span class=\"o\">));<\/span>\n<\/pre>\n<\/div>\n<\/li>\n<\/ul>\n<h2>Le \u00ab\u00a0cast\u00a0\u00bb de type<\/h2>\n<p>Comme nous l&rsquo;avons vu plus haut, le polymorphisme n&rsquo;est pas une conversion. Le fait que l&rsquo;objet est assign\u00e9 \u00e0 une variable d&rsquo;un autre type ne fait pas en sorte que l&rsquo;objet change de type. Il devrait donc \u00eatre possible d&rsquo;assigner une variable d&rsquo;un certain type, vers un type descendant, pourvu que le type de l&rsquo;objet soit conforme au type descendant. Par exemple:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"n\">Animal<\/span> <span class=\"n\">lAnimal<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"n\">Chien<\/span><span class=\"o\">(<\/span><span class=\"s\">\"Fido\"<\/span><span class=\"o\">);<\/span>\n<span class=\"n\">Chien<\/span> <span class=\"n\">lChien<\/span> <span class=\"o\">=<\/span> <span class=\"n\">lAnimal<\/span><span class=\"o\">;<\/span>\n<\/pre>\n<\/div>\n<p>Ici, on voit que puisque l&rsquo;on sait que l&rsquo;objet inclue dans la variable \u00ab\u00a0lAnimal\u00a0\u00bb est de type \u00ab\u00a0Chien\u00a0\u00bb, il ne devrait pas \u00eatre probl\u00e9matique d&rsquo;effectuer l&rsquo;assignation vers la variable \u00ab\u00a0lChien\u00a0\u00bb.<\/p>\n<p>Par contre, il est important de constater que Java doit toujours s&rsquo;assurer, \u00e0 la compilation, que les types sont valides avant d&rsquo;effectuer une validation. Et puisque, ici, le type \u00ab\u00a0Chien\u00a0\u00bb n&rsquo;est pas conforme au type \u00ab\u00a0Animal\u00a0\u00bb, cette assignation sera refus\u00e9e. Il est important de comprendre que le compilateur Java n&rsquo;a pas la responsabilit\u00e9 d&rsquo;analyser le code pour d\u00e9duire le type d&rsquo;un objet. Il ne travaille qu&rsquo;avec les types des expressions (ici, le type des variables).<\/p>\n<p>Il est, malgr\u00e9 tout, possible de sp\u00e9cifier au compilateur Java que l&rsquo;expression doit \u00eatre consid\u00e9r\u00e9 d&rsquo;un certain type. Pour se faire, on utilise un \u00ab\u00a0<strong>cast<\/strong>\u00a0\u00bb de type. Voici l&rsquo;exemple pr\u00e9c\u00e9dent, utilisant un \u00ab\u00a0cast\u00a0\u00bb de type:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"n\">Animal<\/span> <span class=\"n\">lAnimal<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"n\">Chien<\/span><span class=\"o\">(<\/span><span class=\"s\">\"Fido\"<\/span><span class=\"o\">);<\/span>\n<span class=\"n\">Chien<\/span> <span class=\"n\">lChien<\/span> <span class=\"o\">=<\/span> <span class=\"o\">(<\/span><span class=\"n\">Chien<\/span><span class=\"o\">)<\/span><span class=\"n\">lAnimal<\/span><span class=\"o\">;<\/span>\n<\/pre>\n<\/div>\n<p>En effectuant un \u00ab\u00a0cast\u00a0\u00bb, je force d&rsquo;une certaine mani\u00e8re Java \u00e0 consid\u00e9rer mon expression comme \u00e9tant valide. Il est \u00e0 noter qu&rsquo;encore une fois, il ne s&rsquo;agit pas d&rsquo;une conversion (m\u00eame si la syntaxe est la m\u00eame que pour une conversion de types primitifs). Si le \u00ab\u00a0cast\u00a0\u00bb n&rsquo;est pas valide, un exception de type \u00ab\u00a0ClassCastException\u00a0\u00bb sera lanc\u00e9e par Java. Par exemple, ce code lancera un exception:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"n\">Animal<\/span> <span class=\"n\">lAnimal<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"n\">Chien<\/span><span class=\"o\">(<\/span><span class=\"s\">\"Fido\"<\/span><span class=\"o\">);<\/span>\n<span class=\"n\">Chat<\/span> <span class=\"n\">lChat<\/span> <span class=\"o\">=<\/span> <span class=\"o\">(<\/span><span class=\"n\">Chat<\/span><span class=\"o\">)<\/span><span class=\"n\">lAnimal<\/span><span class=\"o\">;<\/span>\n<\/pre>\n<\/div>\n<h2>Validation de type<\/h2>\n<p>Les exemples de \u00ab\u00a0cast\u00a0\u00bb pr\u00e9c\u00e9dents sont bien entendu un peu simplistes. C&rsquo;est la raison pour laquelle aucune validation n&rsquo;est n\u00e9cessaire pour effectuer les \u00ab\u00a0cast\u00a0\u00bb. Dans la r\u00e9alit\u00e9, il est rarement si clair de savoir quel est le type d&rsquo;un objet. Par exemple, supposons que nous voudrions cr\u00e9er une m\u00e9thode qui lance \u00ab\u00a0miauler\u00a0\u00bb dans le cas o\u00f9 l&rsquo;objet est un \u00ab\u00a0Chat\u00a0\u00bb et \u00ab\u00a0aboyer\u00a0\u00bb dans le cas o\u00f9 l&rsquo;objet est un \u00ab\u00a0Chien\u00a0\u00bb. Puisque \u00ab\u00a0Chat\u00a0\u00bb et \u00ab\u00a0Chien\u00a0\u00bb est un \u00ab\u00a0Animal\u00a0\u00bb, je peux cr\u00e9er ma m\u00e9thode avec cette signature:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"kd\">public<\/span> <span class=\"kt\">void<\/span> <span class=\"nf\">criAnimal<\/span><span class=\"o\">(<\/span><span class=\"n\">Animal<\/span> <span class=\"n\">aAnimal<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\n    <span class=\"o\">...<\/span>\n<span class=\"o\">}<\/span>\n<\/pre>\n<\/div>\n<p>Ensuite, il faut ex\u00e9cuter des instructions diff\u00e9rentes en fonction du type de l&rsquo;argument. Il est possible d&rsquo;effectuer ce travail avec du \u00ab\u00a0cast\u00a0\u00bb et des \u00ab\u00a0try\u00a0\u00bb, mais le r\u00e9sultat sera peu \u00e9l\u00e9gant. Java propose une m\u00e9canique simple pour effectuer ce travail. Nous pouvons utiliser l&rsquo;expression \u00ab\u00a0instanceof\u00a0\u00bb. Voici un exemple:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"kd\">public<\/span> <span class=\"kt\">void<\/span> <span class=\"nf\">criAnimal<\/span><span class=\"o\">(<\/span><span class=\"n\">Animal<\/span> <span class=\"n\">aAnimal<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\n    <span class=\"k\">if<\/span> <span class=\"o\">(<\/span><span class=\"n\">aAnimal<\/span> <span class=\"k\">instanceof<\/span> <span class=\"n\">Chien<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\n        <span class=\"o\">((<\/span><span class=\"n\">Chien<\/span><span class=\"o\">)<\/span><span class=\"n\">aAnimal<\/span><span class=\"o\">).<\/span><span class=\"na\">aboyer<\/span><span class=\"o\">();<\/span>\n    <span class=\"o\">}<\/span> <span class=\"k\">else<\/span> <span class=\"k\">if<\/span> <span class=\"o\">(<\/span><span class=\"n\">aAnimal<\/span> <span class=\"k\">instanceof<\/span> <span class=\"n\">Chat<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\n        <span class=\"o\">((<\/span><span class=\"n\">Chat<\/span><span class=\"o\">)<\/span> <span class=\"n\">aAnimal<\/span><span class=\"o\">).<\/span><span class=\"na\">miauler<\/span><span class=\"o\">();<\/span>\n    <span class=\"o\">}<\/span>\n<span class=\"o\">}<\/span>\n<\/pre>\n<\/div>\n<p>\u00c9galement, l&rsquo;exemple pr\u00e9c\u00e9dent nous montre qu&rsquo;il est possible d&rsquo;effectuer un \u00ab\u00a0cast\u00a0\u00bb sans n\u00e9cessairement que ce \u00ab\u00a0cast\u00a0\u00bb servent \u00e0 une assignation.<\/p>\n<p><a href=\"https:\/\/www.louismarchand.me\/index.php\/programmation-orientee-objet-1\/\">Retour<\/a><\/p>\n<p>&nbsp;<\/p>\n<hr>\n<p>Auteur: Louis Marchand<br \/>\n<a href=\"https:\/\/creativecommons.org\/licenses\/by\/4.0\/deed.fr\" target=\"_blank\" rel=\"license noopener noreferrer\"><img decoding=\"async\" src=\"https:\/\/i.creativecommons.org\/l\/by\/4.0\/80x15.png\" alt=\"Creative Commons License\"><\/a><br \/>\nSauf pour les sections sp\u00e9cifi\u00e9es autrement, ce travail est sous licence <a href=\"https:\/\/creativecommons.org\/licenses\/by\/4.0\/deed.fr\" target=\"_blank\" rel=\"license noopener noreferrer\">Creative Commons Attribution 4.0 International<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction La programmation orient\u00e9e objet permet plusieurs avantages majeurs au niveau du code. Nous avons d\u00e9j\u00e0 vu que dans les avantages de ce paradigme, il y a la repr\u00e9sentation plus intuitive de la programmation en repr\u00e9sentant les structures en se basant sur des \u00e9l\u00e9ments r\u00e9els (Produit, Animal, Personnes, etc.) au lieu de se baser sur&hellip; <a class=\"more-link\" href=\"https:\/\/www.louismarchand.me\/index.php\/polymorphisme\/\">Continue reading <span class=\"screen-reader-text\">Polymorphisme<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-73","page","type-page","status-publish","hentry","entry"],"_links":{"self":[{"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/pages\/73","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/comments?post=73"}],"version-history":[{"count":2,"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/pages\/73\/revisions"}],"predecessor-version":[{"id":100,"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/pages\/73\/revisions\/100"}],"wp:attachment":[{"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/media?parent=73"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}