{"id":430,"date":"2021-10-22T18:29:37","date_gmt":"2021-10-22T18:29:37","guid":{"rendered":"https:\/\/www.louismarchand.me\/?page_id=430"},"modified":"2022-10-24T21:15:12","modified_gmt":"2022-10-24T21:15:12","slug":"objet2-heritage-multiple","status":"publish","type":"page","link":"https:\/\/www.louismarchand.me\/index.php\/objet2-heritage-multiple\/","title":{"rendered":"L&rsquo;h\u00e9ritage multiple"},"content":{"rendered":"<h2>Introduction<\/h2>\n<p>L&rsquo;h\u00e9ritage multiple est une fonctionnalit\u00e9 de la programmation orient\u00e9e objet qui consiste \u00e0 permettre \u00e0 une classe d&rsquo;h\u00e9riter de plusieurs autres classes. L&rsquo;h\u00e9ritage multiple permet une meilleure conception orient\u00e9e objet en plus de s&rsquo;assurer de diminuer au maximum la duplication de code et maximiser la r\u00e9utilisabilit\u00e9 des classes. Malheureusement, l&rsquo;h\u00e9ritage multiple ne fait pas l&rsquo;unanimit\u00e9 dans la communaut\u00e9 des concepteurs de langages. La raison pour laquelle plusieurs concepteurs de langage ne s&rsquo;aventurent pas dans l&rsquo;impl\u00e9mentation de l&rsquo;h\u00e9ritage multiple, c&rsquo;est que certaines probl\u00e9matiques apparaissent lorsqu&rsquo;on impl\u00e9mente cette m\u00e9canique. Il est possible de g\u00e9rer ces probl\u00e9matiques, mais au co\u00fbt d&rsquo;un langage plus complexe.<\/p>\n<h2>Les bons c\u00f4t\u00e9s de l&rsquo;h\u00e9ritage multiple<\/h2>\n<p>Dans cette section, je pr\u00e9senterai certains exemples montrant les avantages de l&rsquo;h\u00e9ritage multiple.<\/p>\n<h3>Conception objet<\/h3>\n<p>Souvent, l&rsquo;h\u00e9ritage est utilis\u00e9 pour h\u00e9riter de plusieurs types de classe \u00ab\u00a0desing pattern\u00a0\u00bb, ou bien de classe abstraite permettant la gestion d&rsquo;un certain aspect d&rsquo;un sous-ensemble de classes. Il est par contre possible d&rsquo;utiliser l&rsquo;h\u00e9ritage multiple pour d&rsquo;autres types de besoins. Voici un exemple simple:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-10833 aligncenter\" src=\"https:\/\/www.louismarchand.me\/wp-content\/uploads\/2021\/10\/heritage_multiple_exemple.png\" alt=\"\" width=\"533\" height=\"275\" \/><\/p>\n<p>Dans cet exemple, la gestion du mod\u00e8le (qui peut \u00eatre n&rsquo;importe quoi: Produit, Client, etc.) se fait dans les descendants de la classe Vue. Par contre, si on imagine que la Vue_Ajouter_Modifier et Vue_Lister sont cr\u00e9\u00e9es sous forme de nouvelle page, mais que la Vue_Supprimer se fait simplement avec un panneau adjacent \u00e0 la Vue_Lister, nous avons un cas ou l&rsquo;h\u00e9ritage multiple peut \u00eatre tr\u00e8s logique \u00e0 utiliser.<\/p>\n<h3>Diminution de la duplication de code<\/h3>\n<p>Voici comment Java g\u00e8re les objets Comparable. Un objet Comparable est un objet qui peut \u00eatre compar\u00e9 avec un autre objet du m\u00eame type en utilisant les op\u00e9rations &lt;, &gt;, ==, !=, &lt;= et &gt;=. Pour garder l&rsquo;exemple simple, je n&rsquo;ai mis que 2 classes comparables (Integer et String). Il est important de comprendre qu&rsquo;il existe une grande quantit\u00e9 de classes Comparable (voir: l&rsquo;interface <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/14\/docs\/api\/java.base\/java\/lang\/Comparable.html\">Comparable<\/a>). Il est \u00e0 noter que l&rsquo;exemple est simplifi\u00e9 pour faire ressortir le point; la classe Comparable de Java ne contient qu&rsquo;une m\u00e9thode abstraite, mais qui sert autant \u00e0 g\u00e9rer la relation d&rsquo;\u00e9galit\u00e9 (=) que les relations d&rsquo;ordre (< et >). Mais le point demeure le m\u00eame, mais en plus complexe.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" wp-image-10835 aligncenter\" src=\"https:\/\/www.louismarchand.me\/wp-content\/uploads\/2021\/10\/heritage_multiple_comparable.png\" alt=\"\" width=\"529\" height=\"411\" \/><\/p>\n<p>Le probl\u00e8me ici, c&rsquo;est que la classe Integer h\u00e9rite d\u00e9j\u00e0 de la classe Number, qui permet la gestion des op\u00e9rations sur les nombres. Puisque Java ne g\u00e8re pas l&rsquo;h\u00e9ritage multiple, la classe Comparable doit \u00eatre une interface. Par contre, math\u00e9matiquement, les classes enfants de Comparable devraient seulement impl\u00e9ment\u00e9 une seule m\u00e9thode (&lt; ou &gt;). Si nous supposons que la m\u00e9thode plus petit (&lt;) est impl\u00e9ment\u00e9e (par l&rsquo;enfant de Comparable), voici du pseudo-code qui montre comment impl\u00e9menter les diff\u00e9rentes autres m\u00e9thodes de Comparable. Noter que l&rsquo;objet en cours est repr\u00e9sent\u00e9 par cet_objet (en d&rsquo;autres mots, si on compare \u00e0 Java, \u00ab\u00a0this = cet_objet\u00a0\u00bb):<\/p>\n<div class=\"highlight\">\n<pre>fonction &gt;(autre:Comparable) faire\r\n\tRetourne autre &lt; cet_objet\r\nfin\r\n\r\nfonction !=(autre:Comparable) faire\r\n\tRetourne (cet_objet &lt; autre) ou (cet_objet &gt; autre)\r\nfin\r\n\r\nfonction ==(autre:Comparable) faire\r\n\tRetourne non(cet_objet != autre)\r\nfin\r\n\r\nfonction &gt;=(autre:Comparable) faire\r\n\tRetourne (cet_objet &gt; autre) ou (cet_objet == autre)\r\nfin\r\n\r\nfonction &lt;=(autre:Comparable) faire\r\n\tRetourne (cet_objet &lt; autre) ou (cet_objet == autre)\r\nfin<\/pre>\n<\/div>\n<p>On voit donc que la seule m\u00e9thode de Comparable qui doit r\u00e9ellement \u00eatre impl\u00e9ment\u00e9 dans les Enfants de Comparable, c&rsquo;est &lt; (ou &gt;). Le probl\u00e8me, c&rsquo;est qu&rsquo;en utilisant une interface au lieu d&rsquo;une classe, on doit impl\u00e9menter le code des autres m\u00e9thodes (&gt;, !=, ==, &gt;= et &lt;=) dans toutes les classes enfants de Comparable. En d&rsquo;autres mots, le code ci-dessus doit \u00eatre copi\u00e9-coll\u00e9 int\u00e9gralement dans chaque classe qui impl\u00e9mente comparable; ce qui augmente consid\u00e9rablement la duplication de code impos\u00e9 par la librairie Java.<\/p>\n<p>Pour comparer, voici ce qui est fait par la librairie Eiffel en utilisant l&rsquo;h\u00e9ritage multiple:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" wp-image-10840 aligncenter\" src=\"https:\/\/www.louismarchand.me\/wp-content\/uploads\/2021\/10\/heritage_multiple_comparable_eiffel.png\" alt=\"\" width=\"531\" height=\"278\" \/><\/p>\n<p>On peut donc voir que seulement la m\u00e9thode plus petit (&lt;) est impl\u00e9ment\u00e9e dans les Enfants de Comparable. Toutes les autres m\u00e9thodes sont impl\u00e9ment\u00e9es directement dans la classe Comparable. On diminue donc au maximum la duplication de code impos\u00e9e par la librairie Eiffel.<\/p>\n<h3>Maximiser la r\u00e9utilisabilit\u00e9 des classes.<\/h3>\n<p>Afin d&rsquo;avoir tous les avantages de l&rsquo;h\u00e9ritage, il faut utiliser des classes. Par contre, il arrive que l&rsquo;h\u00e9ritage simple emp\u00eache l&rsquo;utilisation de classes qui pourrait \u00eatre utile. Par exemple, voici un diagramme repr\u00e9sentant une Vue repr\u00e9sentant une fen\u00eatre pouvant \u00eatre observ\u00e9e:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" wp-image-10847 aligncenter\" src=\"https:\/\/www.louismarchand.me\/wp-content\/uploads\/2021\/10\/heritage_multiple_observable.png\" alt=\"\" width=\"527\" height=\"214\" \/><\/p>\n<p>Le probl\u00e8me avec ce diagramme, c&rsquo;est qu&rsquo;elle n\u00e9cessite l&rsquo;h\u00e9ritage multiple pour fonctionner. Afin de construire la m\u00e9canique d&rsquo;observable sans h\u00e9ritage simple, nous allons devoir nous passer de la classe Observable et de placer le code de gestion des Observeurs directement dans la classe Vue. Comme ceci:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-10848 aligncenter\" src=\"https:\/\/www.louismarchand.me\/wp-content\/uploads\/2021\/10\/heritage_simple_observable.png\" alt=\"\" width=\"595\" height=\"240\" \/><\/p>\n<p>Le r\u00e9sultat est que si le responsable de la librairie d&rsquo;Observable\/Observeur fait des am\u00e9liorations \u00e0 sa classe Observable, la classe Vue ne b\u00e9n\u00e9ficiera pas de ces am\u00e9liorations. De plus, si nous avons plusieurs classes Observable, nous ajoutons de la duplication de code (ce qui rejoint le point plus haut).<\/p>\n<h2>Les mauvais c\u00f4t\u00e9s de l&rsquo;h\u00e9ritage multiple<\/h2>\n<p>Il va de soi que, s&rsquo;il n&rsquo;y avait que des avantages \u00e0 l&rsquo;h\u00e9ritage multiple, tous les langages l&rsquo;auraient impl\u00e9ment\u00e9. Il est donc important de comprendre les probl\u00e9matiques que l&rsquo;h\u00e9ritage multiple g\u00e9n\u00e8re. Je vais pr\u00e9senter les 2 aspects probl\u00e9matiques majeurs de l&rsquo;h\u00e9ritage multiple et je vais indiquer comment les langages impl\u00e9mentant l&rsquo;h\u00e9ritage multiple ont contourn\u00e9 le probl\u00e8me.<\/p>\n<h3>Les conflits<\/h3>\n<p>On dit qu&rsquo;il y a conflit lorsque, \u00e0 cause de l&rsquo;h\u00e9ritage multiple, la classe enfant se retrouve avec plusieurs m\u00e9thodes diff\u00e9rentes, avec la m\u00eame signature. Par exemple:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-10850\" src=\"https:\/\/www.louismarchand.me\/wp-content\/uploads\/2021\/10\/heritage_multiple_conflit.png\" alt=\"\" width=\"300\" height=\"181\" \/><\/p>\n<p>Donc, prenons le code suivant:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"n\">Classe_C<\/span> <span class=\"n\">monObjetC<\/span> <span class=\"o\">=<\/span> <span class=\"p\">...;<\/span>\r\n<span class=\"n\">monObjetC<\/span><span class=\"p\">.<\/span><span class=\"na\">f<\/span><span class=\"p\">();<\/span>\r\n<\/pre>\n<\/div>\n<p>La question est donc: \u00ab\u00a0Est-ce que c&rsquo;est la m\u00e9thode f() de Classe_A ou bien la m\u00e9thode f() de Classe_B qui sera lanc\u00e9e? Il est impossible de r\u00e9pondre \u00e0 cette question sans r\u00e9gler le conflit. Les diff\u00e9rents langages ont diff\u00e9rente mani\u00e8re re g\u00e9rer les conflits. Voici des m\u00e9thodes utilis\u00e9es dans diff\u00e9rents langages pour r\u00e9gler les conflits.<\/p>\n<h4>En Python<\/h4>\n<p>En Python, le langage ne g\u00e8re aucun conflit. La m\u00e9thode f() qui sera lanc\u00e9e est la premi\u00e8re m\u00e9thode trouv\u00e9e par Python. Par exemple, si je prends cette classe:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"k\">class<\/span> <span class=\"nc\">Classe_C<\/span><span class=\"p\">(<\/span><span class=\"n\">Classe_A<\/span><span class=\"p\">,<\/span> <span class=\"n\">Classe_B<\/span><span class=\"p\">):<\/span>\r\n<\/pre>\n<\/div>\n<p>La m\u00e9thode f() qui sera lanc\u00e9e est la m\u00e9thode f() de la Classe_A. Inversement, si je prends cette classe:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"k\">class<\/span> <span class=\"nc\">Classe_C<\/span><span class=\"p\">(<\/span><span class=\"n\">Classe_B<\/span><span class=\"p\">,<\/span> <span class=\"n\">Classe_A<\/span><span class=\"p\">):<\/span>\r\n<\/pre>\n<\/div>\n<p>La m\u00e9thode f() qui sera lanc\u00e9e est la m\u00e9thode f() de la Classe_B.<\/p>\n<p>Le gros probl\u00e8me avec cette m\u00e9canique, c&rsquo;est que malgr\u00e9 l&rsquo;absence de conflit, le fait de changer l&rsquo;ordre d&rsquo;h\u00e9ritage change la classe enfant, ce qui n&rsquo;est pas acceptable au niveau orient\u00e9 objet. En d&rsquo;autres mots, une classe qui h\u00e9rite de la Classe_A et de la Classe_B devrait \u00eatre la m\u00eame classe que si elle h\u00e9ritait de la Classe_B et de la Classe_A; ce qui n&rsquo;est pas le cas ici.<\/p>\n<h4>En C++<\/h4>\n<p>Le langage C++ permet de g\u00e9rer les conflits de la mani\u00e8re suivante. Lorsque le client de la classe fait l&rsquo;appel de la fonction f(), il doit obligatoirement sp\u00e9cifier il s&rsquo;agit du f() de quelle classe. Par exemple, le code suivant \u00e9chouera:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"n\">Classe_C<\/span><span class=\"o\">*<\/span> <span class=\"n\">objet_c<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"n\">Classe_C<\/span><span class=\"p\">();<\/span>\r\n<span class=\"n\">objet_c<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">f<\/span><span class=\"p\">();<\/span>\r\n<\/pre>\n<\/div>\n<p>Si nous voulons le faire fonctionner, nous devrons utiliser le code suivant pour utiliser le f() de la Classe_A:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"n\">Classe_C<\/span><span class=\"o\">*<\/span> <span class=\"n\">objet_c<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"n\">Classe_C<\/span><span class=\"p\">();<\/span>\r\n<span class=\"n\">objet_c<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">Classe_A<\/span><span class=\"o\">::<\/span><span class=\"n\">f<\/span><span class=\"p\">();<\/span>\r\n<\/pre>\n<\/div>\n<p>et le code suivant pour utiliser le f() de la Classe_B:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"n\">Classe_C<\/span><span class=\"o\">*<\/span> <span class=\"n\">objet_c<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"n\">Classe_C<\/span><span class=\"p\">();<\/span>\r\n<span class=\"n\">objet_c<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">Classe_B<\/span><span class=\"o\">::<\/span><span class=\"n\">f<\/span><span class=\"p\">();<\/span>\r\n<\/pre>\n<\/div>\n<p>Une autre m\u00e9thode que le client peut utiliser est d&rsquo;utiliser un type diff\u00e9rent pour la variable. Par exemple, ce code lancera le f() de la Classe_A:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"n\">Classe_A<\/span><span class=\"o\">*<\/span> <span class=\"n\">objet_c<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"n\">Classe_C<\/span><span class=\"p\">();<\/span>\r\n<span class=\"n\">objet_c<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">f<\/span><span class=\"p\">();<\/span>\r\n<\/pre>\n<\/div>\n<p>et le code suivant lancera le f() de la Classe_B:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"n\">Classe_B<\/span><span class=\"o\">*<\/span> <span class=\"n\">objet_c<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"n\">Classe_C<\/span><span class=\"p\">();<\/span>\r\n<span class=\"n\">objet_c<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">f<\/span><span class=\"p\">();<\/span>\r\n<\/pre>\n<\/div>\n<p>On peut \u00e9galement \u00ab\u00a0typer\u00a0\u00bb l&rsquo;objet pour s&rsquo;assurer d&rsquo;utiliser la fonction recherch\u00e9e. Par exemple, le code suivant lancera le f() de la Classe_A:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"n\">Classe_C<\/span><span class=\"o\">*<\/span> <span class=\"n\">objet_c<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"n\">Classe_C<\/span><span class=\"p\">();<\/span>\r\n<span class=\"p\">((<\/span><span class=\"n\">Classe_A<\/span><span class=\"o\">*<\/span><span class=\"p\">)<\/span><span class=\"n\">objet_c<\/span><span class=\"p\">)<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">f<\/span><span class=\"p\">();<\/span>\r\n<\/pre>\n<\/div>\n<p>et le code suivant lancera le f() de la Classe_B:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"n\">Classe_C<\/span><span class=\"o\">*<\/span> <span class=\"n\">objet_c<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"n\">Classe_C<\/span><span class=\"p\">();<\/span>\r\n<span class=\"p\">((<\/span><span class=\"n\">Classe_B<\/span><span class=\"o\">*<\/span><span class=\"p\">)<\/span><span class=\"n\">objet_c<\/span><span class=\"p\">)<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">f<\/span><span class=\"p\">();<\/span>\r\n<\/pre>\n<\/div>\n<p>Toutes ces m\u00e9thodes, quoique fonctionnelles, ont \u00e9t\u00e9 critiqu\u00e9es par les experts du domaine des langages de programmation puisqu&rsquo;elles laissent le soin au client de la classe de choisir dans quelle classe parent trouver la m\u00e9thode ou l&rsquo;attribut \u00e0 utiliser. De ce fait, les m\u00e9canismes de gestion de conflit contreviennent au principe d&rsquo;encapsulation, un des piliers du concept orient\u00e9 objet.<\/p>\n<h4>En Eiffel<\/h4>\n<p>Afin de respecter au maximum tous les principes objet, Eiffel s&rsquo;est dot\u00e9 d&rsquo;une section \u00e0 part dans le code d&rsquo;une classe afin de pr\u00e9ciser tout ce qui a \u00e0 pr\u00e9ciser au niveau de l&rsquo;h\u00e9ritage. Ainsi, des m\u00e9canismes plus complexes ont pu \u00eatre d\u00e9velopp\u00e9s afin de g\u00e9rer \u00e9l\u00e9gamment les conflits. Le m\u00e9canisme le plus courant afin de r\u00e9gler un conflit consiste \u00e0 renommer un ou plusieurs attributs ou m\u00e9thodes afin de faire dispara\u00eetre l\u2019ambigu\u00eft\u00e9. Par exemple, ce code de la CLASSE_C donnera une erreur:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"kr\">class<\/span>\r\n\t<span class=\"nc\">CLASSE_C<\/span>\r\n\r\n<span class=\"kr\">inherit<\/span>\r\n\t<span class=\"nc\">CLASSE_A<\/span>\r\n\t<span class=\"nc\">CLASSE_B<\/span>\r\n\r\n<span class=\"kr\">end<\/span>\r\n<\/pre>\n<\/div>\n<p>L&rsquo;erreur nous indique que la CLASSE_C contient deux m\u00e9thodes diff\u00e9rentes avec le m\u00eame nom. Nous pouvons donc renommer une des deux m\u00e9thodes en utilisant la clause \u00ab\u00a0rename\u00a0\u00bb:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"kr\">class<\/span>\r\n\t<span class=\"nc\">CLASSE_C<\/span>\r\n\r\n<span class=\"kr\">inherit<\/span>\r\n\t<span class=\"nc\">CLASSE_A<\/span>\r\n\t\t<span class=\"kr\">rename<\/span>\r\n\t\t\t<span class=\"n\">f<\/span> <span class=\"kr\">as<\/span> <span class=\"n\">f_de_a<\/span>\r\n\t\t<span class=\"kr\">end<\/span>\r\n\t<span class=\"nc\">CLASSE_B<\/span>\r\n\r\n<span class=\"kr\">end<\/span>\r\n<\/pre>\n<\/div>\n<p>Ce code compile sans probl\u00e8me puisqu&rsquo;il n&rsquo;y a plus de conflit. Il aurait \u00e9galement \u00e9t\u00e9 possible de renommer les deux m\u00e9thodes f. Par exemple:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"kr\">class<\/span>\r\n\t<span class=\"nc\">CLASSE_C<\/span>\r\n\r\n<span class=\"kr\">inherit<\/span>\r\n\t<span class=\"nc\">CLASSE_A<\/span>\r\n\t\t<span class=\"kr\">rename<\/span>\r\n\t\t\t<span class=\"n\">f<\/span> <span class=\"kr\">as<\/span> <span class=\"n\">f_de_a<\/span>\r\n\t\t<span class=\"kr\">end<\/span>\r\n\t<span class=\"nc\">CLASSE_B<\/span>\r\n\t\t<span class=\"kr\">rename<\/span>\r\n\t\t\t<span class=\"n\">f<\/span> <span class=\"kr\">as<\/span> <span class=\"n\">f_de_b<\/span>\r\n\t\t<span class=\"kr\">end<\/span>\r\n\r\n<span class=\"kr\">end<\/span>\r\n<\/pre>\n<\/div>\n<p>Dans le cas ou nous ne voudrions seulement une des deux m\u00e9thodes des classes parents, nous pourrions tous simplement demander au compilateur d&rsquo;oublier la m\u00e9thode qui ne nous int\u00e9resse pas avec la clause \u00ab\u00a0undefine\u00a0\u00bb. Par exemple:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"kr\">class<\/span>\r\n\t<span class=\"nc\">CLASSE_C<\/span>\r\n\r\n<span class=\"kr\">inherit<\/span>\r\n\t<span class=\"nc\">CLASSE_A<\/span>\r\n\t<span class=\"nc\">CLASSE_B<\/span>\r\n\t\t<span class=\"kr\">undefine<\/span>\r\n\t\t\t<span class=\"n\">f<\/span>\r\n\t\t<span class=\"kr\">end<\/span>\r\n\r\n<span class=\"kr\">end<\/span>\r\n<\/pre>\n<\/div>\n<p>Une derni\u00e8re possibilit\u00e9 serait de red\u00e9finir la m\u00e9thode f(). Cette m\u00e9thode permet \u00e9galement de cr\u00e9er une seule m\u00e9thode f() dans CLASSE_C qui lancerait autant la m\u00e9thode f() de CLASSE_A et la m\u00e9thode f() de CLASSE_B avec le mot cl\u00e9 \u00ab\u00a0precursor\u00a0\u00bb. Par exemple:<\/p>\n<div class=\"highlight\">\n<pre><span><\/span><span class=\"kr\">class<\/span>\r\n\t<span class=\"nc\">CLASSE_C<\/span>\r\n\r\n<span class=\"kr\">inherit<\/span>\r\n\t<span class=\"nc\">CLASSE_A<\/span>\r\n\t\t<span class=\"kr\">redefine<\/span>\r\n\t\t\t<span class=\"n\">f<\/span>\r\n\t\t<span class=\"kr\">end<\/span>\r\n\t<span class=\"nc\">CLASSE_B<\/span>\r\n\t\t<span class=\"kr\">redefine<\/span>\r\n\t\t\t<span class=\"n\">f<\/span>\r\n\t\t<span class=\"kr\">end<\/span>\r\n\r\n<span class=\"kr\">feature<\/span>\r\n\r\n\t<span class=\"n\">f<\/span>\r\n\t\t<span class=\"kr\">do<\/span>\r\n\t\t\t<span class=\"kc\">Precursor<\/span> <span class=\"p\">{<\/span><span class=\"nc\">CLASSE_A<\/span><span class=\"p\">}<\/span>\r\n\t\t\t<span class=\"kc\">Precursor<\/span> <span class=\"p\">{<\/span><span class=\"nc\">CLASSE_B<\/span><span class=\"p\">}<\/span>\r\n\t\t<span class=\"kr\">end<\/span>\r\n\r\n<span class=\"kr\">end<\/span>\r\n<\/pre>\n<\/div>\n<h2>Le probl\u00e8me du diamant<\/h2>\n<p>Le probl\u00e8me du diamant est le probl\u00e8me le plus important dans le principe d&rsquo;h\u00e9ritage multiple. Il n&rsquo;existe pas de m\u00e9canisme vraiment facile et \u00e9l\u00e9gant \u00e0 ce jour pour g\u00e9rer ce probl\u00e8me. Il est par contre important de sp\u00e9cifier qu&rsquo;heureusement, il est tr\u00e8s rare que ce probl\u00e8me arrive r\u00e9ellement dans un programme r\u00e9el.<\/p>\n<p>Ce probl\u00e8me arrive lorsqu&rsquo;une classe parent sp\u00e9cifie une m\u00e9thode, que plusieurs de ses classes enfants red\u00e9finissent cette m\u00e9thode et que finalement, une classe h\u00e9rite de ces classes enfants. Voici le diagramme de classe repr\u00e9sentant cette situation:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" wp-image-10862 aligncenter\" src=\"https:\/\/www.louismarchand.me\/wp-content\/uploads\/2021\/10\/heritage_multiple_diamant.png\" alt=\"\" width=\"346\" height=\"478\" \/><\/p>\n<p>Cette m\u00e9canique semble similaire au conflit pr\u00e9ciser plus haut, mais la subtilit\u00e9 repose dans un cas d&rsquo;utilisation sp\u00e9cifique. Pour la repr\u00e9senter, voici un exemple Eiffel qui utilise la m\u00e9canique de \u00ab\u00a0rename\u00a0\u00bb indiqu\u00e9e plus haut. Cela devrait vous montrer d&rsquo;o\u00f9 vient la probl\u00e9matique du probl\u00e8me du diagramme.<\/p>\n<p>Premi\u00e8rement, voici la CLASSE_PARENT:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"kr\">deferred<\/span> <span class=\"kr\">class<\/span>\r\n\t<span class=\"nc\">CLASSE_PARENT<\/span>\r\n\r\n<span class=\"kr\">feature<\/span>\r\n\r\n\t<span class=\"n\">f<\/span>\r\n\t\t<span class=\"kr\">deferred<\/span>\r\n\t\t<span class=\"kr\">end<\/span>\r\n<span class=\"kr\">end<\/span>\r\n<\/pre>\n<\/div>\n<p>Les deux classes enfants seront les suivantes:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"kr\">class<\/span>\r\n\t<span class=\"nc\">CLASSE_A<\/span>\r\n\r\n<span class=\"kr\">inherit<\/span>\r\n\t<span class=\"nc\">CLASSE_PARENT<\/span>\r\n\r\n<span class=\"kr\">feature<\/span>\r\n\r\n\t<span class=\"n\">f<\/span>\r\n\t\t<span class=\"kr\">do<\/span>\r\n\t\t\t<span class=\"n\">print<\/span><span class=\"p\">(<\/span><span class=\"s\">\"A%N\"<\/span><span class=\"p\">)<\/span>\r\n\t\t<span class=\"kr\">end<\/span>\r\n\r\n<span class=\"kr\">end<\/span>\r\n<\/pre>\n<\/div>\n<div class=\"highlight\">\n<pre><span class=\"kr\">class<\/span>\r\n\t<span class=\"nc\">CLASSE_B<\/span>\r\n\r\n<span class=\"kr\">inherit<\/span>\r\n\t<span class=\"nc\">CLASSE_PARENT<\/span>\r\n\r\n<span class=\"kr\">feature<\/span>\r\n\r\n\t<span class=\"n\">f<\/span>\r\n\t\t<span class=\"kr\">do<\/span>\r\n\t\t\t<span class=\"n\">print<\/span><span class=\"p\">(<\/span><span class=\"s\">\"B%N\"<\/span><span class=\"p\">)<\/span>\r\n\t\t<span class=\"kr\">end<\/span>\r\n\r\n<span class=\"kr\">end<\/span>\r\n<\/pre>\n<\/div>\n<p>Ensuite, la classe qui h\u00e9rite des deux classes enfants:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"kr\">class<\/span>\r\n\t<span class=\"nc\">CLASSE_C<\/span>\r\n\r\n<span class=\"kr\">inherit<\/span>\r\n\t<span class=\"nc\">CLASSE_B<\/span>\r\n\t\t<span class=\"kr\">rename<\/span>\r\n\t\t\t<span class=\"n\">f<\/span> <span class=\"kr\">as<\/span> <span class=\"n\">f_de_b<\/span>\r\n\t\t<span class=\"kr\">end<\/span>\r\n\t<span class=\"nc\">CLASSE_A<\/span>\r\n\t\t<span class=\"kr\">rename<\/span>\r\n\t\t\t<span class=\"n\">f<\/span> <span class=\"kr\">as<\/span> <span class=\"n\">f_de_a<\/span>\r\n\t\t<span class=\"kr\">end<\/span>\r\n\r\n<span class=\"kr\">end<\/span>\r\n<\/pre>\n<\/div>\n<p>On peut voir que, malgr\u00e9 qu&rsquo;il y a clairement un conflit entre la CLASSE_A et la CLASSE_B, ce conflit est r\u00e9gl\u00e9 en utilisant les clauses \u00ab\u00a0rename\u00a0\u00bb. Maintenant, prenons l&rsquo;utilisation de la part du client. Si j&rsquo;utilise le code suivant:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"n\">make<\/span>\r\n\t<span class=\"kr\">local<\/span>\r\n\t\t<span class=\"n\">objet<\/span><span class=\"p\">:<\/span><span class=\"nc\">CLASSE_C<\/span>\r\n\t<span class=\"kr\">do<\/span>\r\n\t\t<span class=\"n\">objet<\/span> <span class=\"o\">:=<\/span> <span class=\"kr\">create<\/span> <span class=\"p\">{<\/span><span class=\"nc\">CLASSE_C<\/span><span class=\"p\">}<\/span>\r\n\t\t<span class=\"n\">objet<\/span><span class=\"p\">.<\/span><span class=\"n\">f_de_a<\/span>\r\n\t<span class=\"kr\">end<\/span>\r\n<\/pre>\n<\/div>\n<p>On voit que la m\u00e9thode f de la CLASSE_A sera utilis\u00e9e. De la m\u00eame mani\u00e8re, dans le code:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"n\">make<\/span>\r\n\t<span class=\"kr\">local<\/span>\r\n\t\t<span class=\"n\">objet<\/span><span class=\"p\">:<\/span><span class=\"nc\">CLASSE_C<\/span>\r\n\t<span class=\"kr\">do<\/span>\r\n\t\t<span class=\"n\">objet<\/span> <span class=\"o\">:=<\/span> <span class=\"kr\">create<\/span> <span class=\"p\">{<\/span><span class=\"nc\">CLASSE_C<\/span><span class=\"p\">}<\/span>\r\n\t\t<span class=\"n\">objet<\/span><span class=\"p\">.<\/span><span class=\"n\">f_de_b<\/span>\r\n\t<span class=\"kr\">end<\/span>\r\n<\/pre>\n<\/div>\n<p>on voit que la m\u00e9thode f de la CLASSE_B sera utilis\u00e9e. De mani\u00e8re moins \u00e9vidente, dans le code:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"n\">make<\/span>\r\n\t<span class=\"kr\">local<\/span>\r\n\t\t<span class=\"n\">objet<\/span><span class=\"p\">:<\/span><span class=\"nc\">CLASSE_A<\/span>\r\n\t<span class=\"kr\">do<\/span>\r\n\t\t<span class=\"n\">objet<\/span> <span class=\"o\">:=<\/span> <span class=\"kr\">create<\/span> <span class=\"p\">{<\/span><span class=\"nc\">CLASSE_C<\/span><span class=\"p\">}<\/span>\r\n\t\t<span class=\"n\">objet<\/span><span class=\"p\">.<\/span><span class=\"n\">f<\/span>\r\n\t<span class=\"kr\">end<\/span>\r\n<\/pre>\n<\/div>\n<p>le f de la CLASSE_A sera utilis\u00e9, puisque la variable objet est de type CLASSE_A. De la m\u00eame mani\u00e8re, dans le code:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"n\">make<\/span>\r\n\t<span class=\"kr\">local<\/span>\r\n\t\t<span class=\"n\">objet<\/span><span class=\"p\">:<\/span><span class=\"nc\">CLASSE_B<\/span>\r\n\t<span class=\"kr\">do<\/span>\r\n\t\t<span class=\"n\">objet<\/span> <span class=\"o\">:=<\/span> <span class=\"kr\">create<\/span> <span class=\"p\">{<\/span><span class=\"nc\">CLASSE_C<\/span><span class=\"p\">}<\/span>\r\n\t\t<span class=\"n\">objet<\/span><span class=\"p\">.<\/span><span class=\"n\">f<\/span>\r\n\t<span class=\"kr\">end<\/span>\r\n<\/pre>\n<\/div>\n<p>le f de la CLASSE_B sera utilis\u00e9.<\/p>\n<p>Finalement, et c&rsquo;est ici que le probl\u00e8me du diamant prend tout son sens, si on prend le code suivant:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"n\">make<\/span>\r\n\t<span class=\"kr\">local<\/span>\r\n\t\t<span class=\"n\">objet<\/span><span class=\"p\">:<\/span><span class=\"nc\">CLASSE_PARENT<\/span>\r\n\t<span class=\"kr\">do<\/span>\r\n\t\t<span class=\"n\">objet<\/span> <span class=\"o\">:=<\/span> <span class=\"kr\">create<\/span> <span class=\"p\">{<\/span><span class=\"nc\">CLASSE_C<\/span><span class=\"p\">}<\/span>\r\n\t\t<span class=\"n\">objet<\/span><span class=\"p\">.<\/span><span class=\"n\">f<\/span>\r\n\t<span class=\"kr\">end<\/span>\r\n<\/pre>\n<\/div>\n<p>est-ce qu&rsquo;il est possible de savoir quel f sera utilis\u00e9\u2009? En effet, puisque la m\u00e9thode f de la CLASSE_PARENT est abstraite, il faut aller voir dans les classes enfants pour conna\u00eetre l&rsquo;impl\u00e9mentation de la m\u00e9thode. Par contre, il y a deux impl\u00e9mentations diff\u00e9rentes de la m\u00e9thode f dans les enfants de CLASSE_PARENT. Puisque la CLASSE_PARENT est le parent de la CLASSE_A et de la CLASSE_B, et qu&rsquo;en orient\u00e9e objet, un parent ne doit avoir aucune d\u00e9pendance envers leurs enfants (les parents ne connaissent pas les enfants). Logiquement, il pourrait \u00eatre possible que la classe parent soit dans une certaine librairie et que les classes enfants ne sont pas accessible \u00e0 partir de cette librairie. Encore une fois, la solution de ce probl\u00e8me est diff\u00e9rente en fonction du langage utilis\u00e9.<\/p>\n<h4>En Python<\/h4>\n<p>La solution en Python est le m\u00eame que pour la solution des conflits pr\u00e9sent\u00e9e plus haut. Python utilisera la premi\u00e8re m\u00e9thode trouv\u00e9e dans la liste des m\u00e9thodes de l&rsquo;objet. Voir plus haut pour les inconv\u00e9nients de cette solution.<\/p>\n<h4>En C++<\/h4>\n<p>Encore une fois, la solution en C++ est similaire au probl\u00e8me du conflit pr\u00e9sent\u00e9 plus haut. C&rsquo;est-\u00e0-dire qu&rsquo;il faut pr\u00e9ciser dans quelle classe l&rsquo;impl\u00e9mentation se trouve dans l&rsquo;impl\u00e9mentation afin de retirer l&rsquo;ambigu\u00eft\u00e9. Par exemple:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"n\">Classe_Parent<\/span><span class=\"o\">*<\/span> <span class=\"n\">objet<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"n\">Classe_C<\/span><span class=\"p\">();<\/span>\r\n<span class=\"n\">objet<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">Classe_A<\/span><span class=\"o\">::<\/span><span class=\"n\">f<\/span><span class=\"p\">();<\/span>\r\n<\/pre>\n<\/div>\n<p>On voit que l&rsquo;ambigu\u00eft\u00e9 est retir\u00e9 par le fait de sp\u00e9cifier le CLASSE_A dans l&rsquo;appel de m\u00e9thode. Il est \u00e9galement possible d&rsquo;utiliser le \u00ab\u00a0typage\u00a0\u00bb comme ceci:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"n\">Classe_Parent<\/span><span class=\"o\">*<\/span> <span class=\"n\">objet<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"n\">Classe_C<\/span><span class=\"p\">();<\/span>\r\n<span class=\"p\">((<\/span><span class=\"n\">Classe_A<\/span><span class=\"o\">*<\/span><span class=\"p\">)<\/span><span class=\"n\">objet<\/span><span class=\"p\">)<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">f<\/span><span class=\"p\">();<\/span>\r\n<\/pre>\n<\/div>\n<p>Encore une fois, malgr\u00e9 que cette m\u00e9thode est g\u00e9n\u00e9ralement fonctionnelle, un tr\u00e8s grand probl\u00e8me ressort de ces m\u00e9canismes. En effet, la r\u00e8gle du concept orient\u00e9e objet pr\u00e9cisant que les classes ne devraient pas conna\u00eetre leurs enfants devrait \u00e9galement s&rsquo;appliquer aux clients de la classe. En d&rsquo;autres mots, la classe qui utilise une variable de type Classe_Parent ne devrait pas prendre en consid\u00e9ration que cette Classe_Parent a des enfants. De mani\u00e8re encore plus importante, du code compl\u00e8tement fonctionnel peut se retrouver non fonctionnel \u00e0 cause de l&rsquo;ajout d&rsquo;h\u00e9ritage. Par exemple, prenons une librairie logicielle ind\u00e9pendante qui contient une classe abstraite avec une m\u00e9thode (similaire la notre Classe_Parent) et une autre classe de la librairie utilise la m\u00e9thode de cette classe abstraite. Les classes de cette librairie logicielle peuvent \u00eatre correctement compil\u00e9es sans erreur. Par la suite, on inclut cette librairie dans un autre projet logiciel et dans ce projet, on ajoute les classes enfants qui cr\u00e9\u00e9 le \u00ab\u00a0desing\u00a0\u00bb en diamant. On obtient donc que le code qui ne compile pas ne se trouve pas dans le projet en tant que tel, mais dans la librairie qui compilait correctement avant d&rsquo;avoir \u00e9t\u00e9 incluse au projet. Cette probl\u00e9matique ne brise pas simplement les concepts orient\u00e9s objet, mais bien les concepts de bases des d\u00e9pendances logiciels en g\u00e9n\u00e9ral.<\/p>\n<h4>En Eiffel<\/h4>\n<p>Afin de respecter les principes orient\u00e9s objet au maximum, Eiffel permet une autre section dans sa clause d&rsquo;h\u00e9ritage. Cette clause est la clause \u00ab\u00a0select\u00a0\u00bb et cette clause ne s&rsquo;applique uniquement que dans le cas d&rsquo;un probl\u00e8me du diamant. Il est donc assez rare de voir cette clause appara\u00eetre dans un code Eiffel. Donc, si je r\u00e8gle le probl\u00e8me du diamant pr\u00e9sent\u00e9 plus haut, je ne fais qu&rsquo;ajouter la clause \u00ab\u00a0select\u00a0\u00bb suivante:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"kr\">class<\/span>\r\n\t<span class=\"nc\">CLASSE_C<\/span>\r\n\r\n<span class=\"kr\">inherit<\/span>\r\n\t<span class=\"nc\">CLASSE_B<\/span>\r\n\t\t<span class=\"kr\">rename<\/span>\r\n\t\t\t<span class=\"n\">f<\/span> <span class=\"kr\">as<\/span> <span class=\"n\">f_de_b<\/span>\r\n\t\t<span class=\"kr\">end<\/span>\r\n\t<span class=\"nc\">CLASSE_A<\/span>\r\n\t\t<span class=\"kr\">rename<\/span>\r\n\t\t\t<span class=\"n\">f<\/span> <span class=\"kr\">as<\/span> <span class=\"n\">f_de_a<\/span>\r\n\t\t<span class=\"kr\">select<\/span>\r\n\t\t\t<span class=\"n\">f_de_a<\/span>\r\n\t\t<span class=\"kr\">end<\/span>\r\n\r\n<span class=\"kr\">end<\/span>\r\n<\/pre>\n<\/div>\n<p>Cette clause indique au compilateur que, s&rsquo;il se trouve avec le dernier exemple \u00ab\u00a0make\u00a0\u00bb pr\u00e9sent\u00e9 plus haut, la m\u00e9thode f de la CLASSE_A (ou f_de_a) sera utilis\u00e9e.<\/p>\n<p>Ce m\u00e9canisme respecte le principe orient\u00e9 objet puisqu&rsquo;elle est sp\u00e9cifi\u00e9e dans le dernier enfant de l&rsquo;h\u00e9ritage du \u00ab\u00a0d\u00e9sing\u00a0\u00bb en diamant et que, puisque les enfants peuvent conna\u00eetre leurs parents, le principe de d\u00e9pendance est respect\u00e9.<\/p>\n<h2>H\u00e9ritage r\u00e9pp\u00e9t\u00e9e<\/h2>\n<p>Lorsqu&rsquo;une classe h\u00e9rite directement plusieurs fois de la m\u00eame classe, on a un cas d&rsquo;h\u00e9ritage r\u00e9p\u00e9t\u00e9.<\/p>\n<p>Autre qu&rsquo;Eiffel, aucun langage (que je connais) n&rsquo;impl\u00e9mente ce type d&rsquo;h\u00e9ritage.<\/p>\n<p>Gr\u00e2ce aux m\u00e9caniques de \u00ab\u00a0rename\u00a0\u00bb et de \u00ab\u00a0select\u00a0\u00bb de Eiffel, il est possible d&rsquo;utiliser, de mani\u00e8re assez efficace, l&rsquo;h\u00e9ritage r\u00e9p\u00e9t\u00e9 en Eiffel. D&rsquo;ailleurs, les classes <a href=\"https:\/\/www.eiffel.org\/files\/doc\/static\/22.05\/libraries\/base\/two_way_chain_iterator_chart.html\" target=\"_blank\" rel=\"noopener\">\u00ab\u00a0TWO_WAY_CHAIN_ITERATOR\u00a0\u00bb<\/a> et <a href=\"https:\/\/www.eiffel.org\/files\/doc\/static\/22.05\/libraries\/base\/cursor_tree_iterator_chart.html\" target=\"_blank\" rel=\"noopener\">\u00ab\u00a0CURSOR_TREE_ITERATOR\u00a0\u00bb<\/a> utilisent l&rsquo;h\u00e9ritage r\u00e9p\u00e9t\u00e9.<\/p>\n<h2>\u00c0 propos des interfaces<\/h2>\n<p>Aujourd&rsquo;hui, la majorit\u00e9 des langages de programmation h\u00e9rite des langages C et C++. Lorsque les cr\u00e9ateurs de langage comme Java et C# ont d\u00e9velopp\u00e9 leurs langages, ils ont introduit le principe d&rsquo;interface pour remplacer l&rsquo;h\u00e9ritage multiple dans leur langage. Cette section pr\u00e9sente d&rsquo;o\u00f9 vient l&rsquo;id\u00e9e des interfaces et \u00e0 quelle mesure \u00e7a remplace l&rsquo;h\u00e9ritage multiple par classes.<\/p>\n<h3>Historique<\/h3>\n<p>Lors des sections pr\u00e9c\u00e9dentes, nous avons vu que la gestion des conflits en C++ (particuli\u00e8rement dans un cas de \u00ab\u00a0desing\u00a0\u00bb en diamant) \u00e9tait d\u00e9ficiente et brisait beaucoup de concepts importants dans le domaine de la programmation. Voir la section pr\u00e9c\u00e9dente pour plus de d\u00e9tails.<\/p>\n<p>Afin de r\u00e9gler ces probl\u00e9matiques, une r\u00e8gle non \u00e9crite et non officielle a commenc\u00e9 \u00e0 circuler dans la communaut\u00e9 de programmeur C++. La r\u00e8gle est la suivante. Dans l&rsquo;arbre d&rsquo;h\u00e9ritage d&rsquo;une classe, une seule branche d&rsquo;h\u00e9ritage peut contenir des classes effectives et des classes abstraites contenant des attributs ou des m\u00e9thodes impl\u00e9ment\u00e9es. L&rsquo;h\u00e9ritage multiple peut \u00eatre utilis\u00e9, mais seulement si toutes les autres branches d&rsquo;h\u00e9ritage contiennent uniquement des classes abstraites qui contiennent uniquement des m\u00e9thodes abstraites. Cette r\u00e8gle a donn\u00e9 naissance au patron conceptuel d&rsquo;interface.<\/p>\n<p>Puisque les langages comme Java et C# sont grandement bas\u00e9s sur C et C++, ils ont d\u00e9cid\u00e9 d&rsquo;inclure cette r\u00e8gle non \u00e9crite dans le langage en permettant uniquement l&rsquo;h\u00e9ritage simple et de l&rsquo;h\u00e9ritage multiple d&rsquo;interfaces.<\/p>\n<p>En d&rsquo;autres mots, la principale raison pour laquelle les langages populaires d&rsquo;aujourd&rsquo;hui comme Java et C# n&rsquo;ont pas tous les avantages que l&rsquo;h\u00e9ritage multiple propose, est que C++ a mal impl\u00e9ment\u00e9 ce type d&rsquo;h\u00e9ritage.<\/p>\n<h3>Avantages et limites des interfaces<\/h3>\n<p>L&rsquo;h\u00e9ritage multiple sous la forme d&rsquo;interface a tout de m\u00eame certains avantages. En effet, en plus d&rsquo;\u00e9viter compl\u00e8tement les conflits dans l&rsquo;h\u00e9ritage, elle permet l&rsquo;utilisation du polymorphisme. En effet, sans ce type d&rsquo;interface, des \u00ab\u00a0desing\u00a0\u00bb comme Observeur, M\u00e9diateur, Listener, etc. ne serait pas possible.<\/p>\n<p>Il est par contre important de noter les limites de ce type d&rsquo;h\u00e9ritage. En effet, comme nous l&rsquo;avons vu plus haut, l&rsquo;h\u00e9ritage par interface diminue significativement la r\u00e9utilisabilit\u00e9 des classes et oblige l&rsquo;utilisation de duplication de code dans certains contextes. \u00c9galement, de mani\u00e8re structurelle, le langage (et potentiellement toutes les classes) se retrouve avec deux arbres d&rsquo;h\u00e9ritage ind\u00e9pendants, ce qui peut complexifier la documentation et l&rsquo;utilisation des classes du syst\u00e8me.<br \/>\n<a href=\"https:\/\/www.louismarchand.me\/index.php\/les-cours\/programmation-orientee-objet-2\/\">Retour<\/a><\/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 L&rsquo;h\u00e9ritage multiple est une fonctionnalit\u00e9 de la programmation orient\u00e9e objet qui consiste \u00e0 permettre \u00e0 une classe d&rsquo;h\u00e9riter de plusieurs autres classes. L&rsquo;h\u00e9ritage multiple permet une meilleure conception orient\u00e9e objet en plus de s&rsquo;assurer de diminuer au maximum la duplication de code et maximiser la r\u00e9utilisabilit\u00e9 des classes. Malheureusement, l&rsquo;h\u00e9ritage multiple ne fait pas&hellip; <a class=\"more-link\" href=\"https:\/\/www.louismarchand.me\/index.php\/objet2-heritage-multiple\/\">Continue reading <span class=\"screen-reader-text\">L&rsquo;h\u00e9ritage multiple<\/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-430","page","type-page","status-publish","hentry","entry"],"_links":{"self":[{"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/pages\/430","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=430"}],"version-history":[{"count":8,"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/pages\/430\/revisions"}],"predecessor-version":[{"id":736,"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/pages\/430\/revisions\/736"}],"wp:attachment":[{"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/media?parent=430"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}