Java omet l'héritage multiple au motif qu'il évite l'objectif de conception de garder le langage simple .
Je me demande si Java (avec son écosystème) est vraiment "simple". Python n'est pas complexe et possède plusieurs héritages. Donc, sans être trop subjectif, ma question est ...
Quels sont les modèles de problèmes typiques qui bénéficient d'un code conçu pour faire un usage intensif de l'héritage multiple
multiple-inheritance
treecoder
la source
la source
Réponses:
Avantages :
Les inconvénients :
En C ++, un bon exemple d'héritage multiple utilisé pour composer des entités orthogonales est lorsque vous utilisez CRTP pour, par exemple, configurer un système de composants pour un jeu.
J'ai commencé à écrire un exemple, mais je pense qu'il vaut mieux regarder un exemple du monde réel. Certains codes d'Ogre3D utilisent l'héritage multiple de manière agréable et très intuitive. Par exemple, la classe Mesh hérite à la fois de Resources et d'AnimationContainer. Les ressources exposent l'interface commune à toutes les ressources et AnimationContainer expose l'interface spécifique pour la manipulation d'un ensemble d'animations. Ils ne sont pas liés, il est donc facile de considérer un maillage comme une ressource qui peut en outre contenir un ensemble d'animations. Sent naturel n'est-ce pas?
Vous pouvez regarder d' autres exemples dans cette bibliothèque , comme la façon dont l'allocation de mémoire est gérée de manière fine en faisant en sorte que les classes héritent des variantes d'une classe CRTP surchargeant new et delete.
Comme nous l'avons dit, les principaux problèmes d'héritage multiple découlent du mélange de concepts liés. Cela oblige le langage à définir des implémentations complexes (voir la façon dont C ++ permet de jouer avec le problème du diamant ...) et l'utilisateur n'est pas sûr de ce qui se passe dans cette implémentation. Par exemple, lisez cet article expliquant comment il est implémenté en C ++ .
Le supprimer de la langue permet d'éviter les personnes qui ne savent pas comment la langue est appliquée pour rendre les choses mauvaises. Mais cela oblige à penser d'une manière qui, parfois, ne semble pas naturelle, même si ce sont des cas marginaux, cela arrive plus souvent que vous ne le pensez.
la source
Il existe un concept appelé mixins qui est largement utilisé dans les langages plus dynamiques. L'héritage multiple est une façon dont les mixins peuvent être supportés par un langage. Les mixins sont généralement utilisés comme moyen pour une classe d'accumuler différentes fonctionnalités. Sans héritage multiple, vous devez utiliser l'agrégation / délégation pour obtenir un comportement de type mixin avec une classe, ce qui est un peu plus lourd en syntaxe.
la source
Je pense que le choix est principalement basé sur des problèmes dus au problème du diamant .
De plus, il est souvent possible de contourner l'utilisation de l'héritage multiple par délégation ou par d'autres moyens.
Je ne suis pas sûr du sens de votre dernière question. Mais si c'est "dans quels cas l'héritage multiple est-il utile?", Alors dans tous les cas où vous aimeriez avoir un objet A ayant des fonctionnalités des objets B et C, en gros.
la source
Je ne m'étendrai pas beaucoup ici mais vous pouvez sûrement comprendre l'héritage multiple en python via le lien suivant http://docs.python.org/release/1.5.1p1/tut/multiple.html :
...
Ce n'est qu'un petit paragraphe mais suffisamment grand pour dissiper les doutes, je suppose.
la source
Un endroit où l'héritage multiple serait utile est une situation où une classe implémente plusieurs interfaces, mais vous souhaitez avoir une fonctionnalité par défaut intégrée à chaque interface. Ceci est utile si la plupart des classes qui implémentent une interface veulent faire quelque chose de la même manière, mais parfois vous devez faire quelque chose de différent. Vous pouvez avoir chaque classe avec la même implémentation, mais il est plus logique de la pousser vers le haut en un seul endroit.
la source
Ce n'est qu'un exemple, mais celui que je trouve inestimable pour améliorer la sécurité et atténuer les tentations d'appliquer des changements en cascade à travers les appelants ou les sous-classes.
Là où j'ai trouvé l'héritage multiple incroyablement utile, même pour les interfaces sans état les plus abstraites, c'est l'idiome d'interface non virtuelle (NVI) en C ++.
Ce ne sont même pas vraiment des classes de base abstraites autant que des interfaces qui ont juste un peu d'implémentation pour appliquer les aspects universels de leurs contrats, car elles ne réduisent pas vraiment la généralité du contrat autant qu'elles le font mieux. .
Exemple simple (certains pourraient vérifier qu'un descripteur de fichier transmis est ouvert ou quelque chose comme ça):
Dans ce cas, peut
f
- être est appelé par mille endroits dans la base de code, tandis quef_impl
est remplacé par une centaine de sous-classes.Il serait difficile de faire ce genre de contrôle de sécurité dans les 1000 lieux qui appellent
f
ou dans les 100 lieuxf_impl
.En ne faisant que ce point d'entrée à la fonctionnalité non virtuelle, cela me donne un endroit central pour effectuer cette vérification. Et cette vérification ne réduit pas du tout l'abstraction, car elle affirme simplement une condition préalable requise pour appeler cette fonction. Dans un sens, cela renforce sans doute le contrat fourni par l'interface et soulage le fardeau de la vérification de l'
x
entrée pour s'assurer qu'elle est conforme aux conditions préalables valides dans les 100 endroits qui la remplacent.C'est quelque chose que je souhaite que chaque langage ait, et souhaite également, même en C ++, que ce soit un peu plus un concept natif (ex: ne pas nous obliger à définir une fonction distincte pour remplacer).
Ceci est extrêmement utile si vous ne l'avez pas fait
assert
à l'avance et que vous vous en êtes rendu compte plus tard lorsque certains endroits aléatoires de la base de code rencontraient des valeurs négatives transmisesf
.la source
Premièrement: plusieurs copies de la classe de base (un problème C ++) et un couplage étroit entre les classes de base et dérivées.
Deuxièmement: l'héritage multiple des interfaces abstraites
la source