C’est un bon concept pour utiliser l’héritage multiple, ou je peux faire d’autres choses au lieu de cela ?
Réponses
Trop de publicités?L'héritage Multiple, les odeurs, ce qui signifie que, généralement, il a été fait pour de mauvaises raisons, et elle va se faire sauter en arrière dans le visage de la responsable.
Résumé
- Envisager la composition de fonctions, au lieu de l'héritage
- Méfiez-vous du Diamant, de l'Effroi
- Envisagez l'héritage de plusieurs interfaces au lieu d'objets
- Parfois, l'Héritage Multiple est la bonne chose. Si elle l'est, puis l'utiliser.
- Être prêt à les défendre de plusieurs hérité de l'architecture dans des revues de code
1. Peut-être la composition?
Cela est vrai pour l'héritage, et donc, c'est encore plus vrai pour l'héritage multiple.
Est-ce que votre objet a vraiment besoin de l'autre? Une Voiture n'a pas besoin d'hériter d'un Moteur à travailler, ni à partir d'une Roue. Une Voiture a un Moteur et quatre Roues.
Si vous utilisez l'héritage multiple pour résoudre ce problème au lieu de composition, alors que vous avez fait quelque chose de mal.
2. Le Diamant de l'Effroi
Généralement, vous avez une classe A, puis B et C héritent de A. Et ne me demandez pas pourquoi, quelqu'un décide alors que D doit hériter à la fois de B et C.
J'ai rencontré ce genre de problème deux fois en 8 huit ans, et il est amusant de voir à cause de:
- Combien une erreur, il a été depuis le début (Dans les deux cas, D ne doit pas avoir hérité des deux B anc C), parce que c'est une mauvaise architecture (en fait, C ne devrait pas avoir existé...)
- Combien de responsables qui ont payé pour ça, parce qu'en C++, le parent de la classe a est présent deux fois dans son petit-enfant de la classe D, et donc, la mise à jour de l'un des parents du champ::champ destiné à jour deux fois (par l'intermédiaire de B: champ a:et C::champ), ou qui ont quelque chose se passe en silence de mal et de crash, plus tard (nouveau un pointeur dans B::champ, et supprimer C::champ...)
En utilisant le mot-clé virtuelle en C++, l'annulation de la double mise en page décrit ci-dessus, mais de toute façon, vous êtes probablement fait quelque chose de mal...
Dans la hiérarchie de l'Objet, vous devez garder l'hiérarchique comme un Arbre (un nœud a UN parent), non pas comme un graphe.
3. Interfaces
L'héritage Multiple de zéro ou un béton de classe, et de zéro ou plusieurs interfaces est généralement Ok, parce que vous ne rencontrerez pas le Diamant de l'Effroi décrit ci-dessus. En fait, c'est la façon dont les choses sont faites en Java.
Généralement, ce que vous voulez dire quand C hérite de A et B est que les utilisateurs peuvent utiliser C comme si c'était un A, et/ou comme si c'était un B.
En C++, une interface est une classe abstraite qui a:
- tous sa méthode déclarée virtuelle pure (suffixé par = 0)
- aucun membre variables
L'héritage Multiple de zéro à un objet réel, et zéro ou plusieurs interfaces n'est pas considéré comme "puant" (au moins, pas autant)
4. Avez-vous vraiment besoin de l'Héritage Multiple?
Parfois, oui.
Habituellement, votre classe C hérite de A et B, et A et B sont deux objets indépendants (c'est à dire pas dans la même hiérarchie, rien en commun, différents concepts, etc.).
Par exemple, vous pourriez avoir un système de Nœuds avec X,Y,Z coordonnées, capable de faire beaucoup de calculs géométriques (peut-être un point, une partie des objets géométriques) et chaque Nœud est un Agent Automatisé, capable de communiquer avec d'autres agents.
Peut-être que vous avez déjà accès à deux bibliothèques, chacune avec son propre espace de noms (une autre raison d'utiliser des espaces de noms... Mais vous utilisez les espaces de noms, n'est-ce pas?), un être "geo" et l'autre bing "ai"
Si vous avez votre propre "propre::Node" découlent à la fois de "ia::Agent" et "geo::Point".
C'est le moment où vous devriez vous demander si vous ne devriez pas utiliser la composition à la place. Si "propres::Node" est vraiment à la fois une "ia::Agent" et un "geo::Point", puis la composition ne serait pas le faire.
Ensuite, vous aurez besoin de l'héritage multiple, d'avoir votre "propre::Node" communiquer avec d'autres agents en fonction de leur position dans un espace 3D.
(Vous remarquerez que l'ia: Agent et geo::Point sont complètement, totalement, entièrement INDÉPENDANTS... C'est ce qui réduit considérablement le danger de l'héritage multiple)
5. Donc, dois-je faire de l'Héritage Multiple?
La plupart du temps, non. MI n'est pas le bon outil, même s'il semble que cela fonctionne.
Mais parfois, oui. Et à ce moment, rien ne fonctionne mieux que des MI, et vous n'aurez pas un Diamant, de l'Effroi, et que votre objet est vraiment à la fois son parent.
Mais parce que MI est puant, être prêt à les défendre de l'architecture dans des revues de code (et la défense c'est une bonne chose, parce que si vous n'êtes pas en mesure de le défendre, alors vous ne devriez pas le faire).
À partir d'un entretien avec Bjarne Stroustrup:
Des gens tout à fait correctement dire que vous n'avez pas besoin de l'héritage multiple, parce que tout ce que vous pouvez faire avec l'héritage multiple, vous pouvez aussi le faire avec de l'héritage simple. Il vous suffit d'utiliser la délégation truc que j'ai mentionné. En outre, vous n'avez pas besoin de tout héritage à tous, parce que tout ce que vous faites avec l'héritage simple, vous pouvez aussi le faire sans héritage par la réexpédition dans le cadre d'une classe. En fait, vous n'avez pas besoin de toutes les classes, parce que vous pouvez tout faire avec des pointeurs et structures de données. Mais pourquoi voudriez-vous faire cela? Quand il est commode d'utiliser la langue des installations? Quand préférez-vous une solution? J'ai vu des cas où l'héritage multiple est utile, et j'ai même vu des cas où, très compliqué héritage multiple est utile. Généralement, je préfère utiliser les facilités offertes par la langue pour faire des solutions de contournement
Il n'y a pas de raison pour l'éviter et il peut être très utile dans certaines situations. Vous devez être conscient des problèmes potentiels.
Le plus important étant le diamant de la mort:
class GrandParent;
class Parent1 : public GrandParent;
class Parent2 : public GrandParent;
class Child : public Parent1, public Parent2;
Vous avez maintenant deux "copies" de grand-parent de l'Enfant.
C++ a pensé à cela et vous permet de faire virtuel héritage, afin de contourner les problèmes.
class GrandParent;
class Parent1 : public virtual GrandParent;
class Parent2 : public virtual GrandParent;
class Child : public Parent1, public Parent2;
Toujours à l'examen de votre conception, vous assurer que vous n'utilisez pas héritage à sauvegarder sur la réutilisation des données. Si vous pouvez représentent la même chose avec la composition (et vous pouvez généralement) c'est une bien meilleure approche.
Voir w:l'Héritage Multiple.
L'héritage Multiple a reçu la critique et en tant que tel, n'est pas mis en œuvre dans de nombreuses langues. Critiques comprend:
- L'accroissement de la complexité
- L'ambiguïté sémantique est souvent résumée comme le diamant problème.
- Ne pas être en mesure explicitement hériter plusieurs fois à partir d'un seul classe
- L'ordre de la succession changer de classe sémantique.
L'héritage Multiple dans les langues avec C++/Java style constructeurs aggrave le problème de l'héritage les constructeurs et constructeur de chaînage, créant ainsi de l'entretien et de la l'extensibilité des problèmes dans ces les langues. Les objets en héritage relations avec très variables les méthodes de construction sont difficiles à dans le cadre du constructeur le chaînage de paradigme.
D'une façon moderne de la résolution de cette interface (pure classe abstraite) comme COM et Java de l'interface.
Je peux faire d'autres choses à la place de cela?
Oui, vous le pouvez. Je vais voler de GoF.
- Programme pour une Interface, pas de mise en Œuvre
- Préférez la composition au cours de l'héritage
Public l'héritage est une relation " EST-UN, et parfois, une classe sera un type de plusieurs classes différentes, et parfois, il est important de tenir compte de cela.
"Mixin" sont aussi parfois utile. Ils sont généralement de petites classes, généralement pas hériter de quoi que ce soit, de fournir des fonctionnalités utiles.
Tant que la hiérarchie d'héritage est relativement peu profond (comme presque toujours), et bien gérée, vous avez peu de chances d'obtenir le redouté de diamant de l'héritage. Le diamant n'est pas un problème avec toutes les langues que l'utilisation de l'héritage multiple, mais le C++de traitement est souvent maladroit et parfois déroutante.
Alors que j'ai couru dans les cas où l'héritage multiple est très pratique, ils sont en fait assez rares. C'est probablement parce que je préfère utiliser d'autres méthodes de conception lorsque je n'ai pas vraiment besoin de l'héritage multiple. Je ne préfère éviter de confondre les constructions de langage, et il est facile de construire l'héritage cas où vous avez à lire le manuel très bien à comprendre ce qu'il se passe.