Je sais que la question a été discuté avant mais il semble toujours que l'héritage soit au moins parfois préférable à la composition. J'aimerais remettre en question cette hypothèse dans l'espoir de mieux comprendre.
Ma question est la suivante : Depuis la composition d'objets permet d'accomplir tout ce que l'on peut accomplir avec l'héritage classique. et puisque l'héritage classique est très souvent malmené [1]. et puisque La composition de l'objet délégué vous donne la flexibilité de changer l'objet délégué en cours d'exécution, pourquoi voudrais-tu jamais utiliser l'héritage classique ?
Je peux en quelque sorte comprendre pourquoi vous recommandez l'héritage dans certains langages comme Java et C++ qui n'offrent pas de syntaxe pratique pour la délégation. Dans ces langages, vous pouvez économiser beaucoup de frappe en utilisant l'héritage chaque fois qu'il n'est pas clairement incorrect de le faire. Mais d'autres langages comme Objective C et Ruby offrent à la fois l'héritage classique et l'héritage par délégation. et syntaxe très pratique pour la délégation. Le langage de programmation Go est le seul langage qui, à ma connaissance, a décidé que l'héritage classique est plus compliqué qu'il n'en vaut la peine et ne supporte que la délégation pour la réutilisation du code.
Une autre façon de formuler ma question est la suivante : Même si vous savez que l'héritage classique n'est pas incorrect pour implémenter un certain modèle, est-ce une raison suffisante pour l'utiliser au lieu de la composition ?
[1] De nombreuses personnes utilisent l'héritage classique pour atteindre le polymorphisme au lieu de laisser leurs classes implémenter une interface. Le but de l'héritage est la réutilisation du code, pas le polymorphisme. De plus, certaines personnes utilisent l'héritage pour modéliser leur compréhension intuitive d'une relation "is-a". ce qui peut souvent poser problème .
Mise à jour
Je veux juste clarifier ce que je veux dire exactement quand je parle d'héritage :
Je parle de le type d'héritage par lequel une classe hérite d'une classe de base partiellement ou totalement implémentée . Je suis pas Vous parlez d'hériter d'une classe de base purement abstraite, ce qui revient à implémenter une interface, ce que, pour mémoire, je ne conteste pas.
Mise à jour 2
Je comprends que l'héritage est le seul moyen de réaliser le polymorphisme en C++. Dans ce cas, la raison pour laquelle vous devez l'utiliser est évidente. Ma question se limite donc à des langages comme Java ou Ruby qui offrent des moyens distincts de réaliser le polymorphisme (interfaces et duck typing, respectivement).
3 votes
"Pourquoi utiliser l'héritage classique ?" D'abord, vous devriez probablement poser la question opposée. Pourquoi n'utiliseriez-vous pas l'héritage classique ? Si un langage offre un concept (l'héritage dans ce cas), l'éviter à cause de "croyances religieuses" ajoute simplement des obstacles inutiles. Il y a toujours plusieurs façons de faire quelque chose. Vous pourriez également poser de nombreuses autres questions similaires - "si vous pouvez programmer en asm, pourquoi auriez-vous besoin du C, et si vous pouvez programmer en C++, pourquoi utiliseriez-vous Python ? Ce n'est qu'un outil parmi d'autres - on l'utilise ou on ne l'utilise pas.
11 votes
@SigTerm De nombreux langages, même modernes, supportent le goto. Une bonne raison pas d'utiliser une fonctionnalité du langage est lorsqu'elle introduit une complexité inutile. J'essaie simplement de comprendre quels sont les avantages - s'il y en a - de l'héritage qui justifieraient la complexité supplémentaire.
0 votes
@KaptajnKold : "goto" J'ai vu des situations où goto était utile. En langage moderne. "La complexité supplémentaire en vaudrait la peine" La complexité supplémentaire apparaît lorsque vous essayez de tout faire en évitant l'héritage. Disons que vous avez une liste de "ressources" quelque part qui doit être traitée de manière spéciale, et que vous voulez ajouter un nouveau type de ressource. Avec l'héritage (multiple), cela peut être fait en quelques lignes de code - vous ajoutez à l'objet les propriétés/comportement de la ressource. En utilisant la composition... disons que ce sera plus compliqué.
2 votes
@SigTerm Peut-être qu'en Java, ce serait plus complexe, mais certainement pas en Objective C, Ruby, Go, JavaScript, SmallTalk ou tout autre langage disposant de meilleurs moyens d'exprimer la composition. J'ai déjà mentionné que je peux voir l'intérêt d'utiliser l'héritage si cela permet d'avoir un code moins verbeux, mais est-ce vraiment le but de l'héritage ? uniquement avantage ? Si oui, cela signifie-t-il qu'il a pas de dans les langues offrant un bon support syntaxique pour la composition ?
1 votes
Les interfaces sont un artifice dans les langages dans lesquels elles existent pour éviter d'avoir à traiter les problèmes perçus de l'héritage multiple.
0 votes
Assurez-vous de lire le Y a-t-il quelque chose que la composition ne peut pas accomplir et que l'héritage peut faire ? Cette question est, dans l'esprit, presque une copie de celle-ci.
0 votes
C'est au moins en partie subjectif, et le PO se dispute avec des personnes dans les commentaires. Pour moi, cela en fait une question subjective et argumentée. Vote de clôture. (Si c'était juste une exposition des points de vue des gens sur le sujet, je ne voterais pas pour la fermeture, mais les longues discussions dans les commentaires ne conviennent pas à l'OS).
0 votes
J'ai eu exactement la même idée, voir devnet.jetbrains.com/message/5478759
0 votes
Vous pouvez expérimenter avec l'annotation @Delegate de Groovy qui est plus puissante que la construction de délégué de Go. Envoyez-moi un mail à jeti789 -at- web -dot- de si vous souhaitez en discuter plus avant.
0 votes
Duplicata très proche : L'héritage est-il vraiment nécessaire ? y Y a-t-il quelque chose que la composition ne peut pas accomplir et que l'héritage peut accomplir ?
23 votes
C'est une honte que des questions comme celle-ci soient fermées et étiquetées "non constructives". Il semble que les administrateurs se plaignent de poser des questions simples que quelqu'un peut simplement chercher, mais bloquent ensuite cette question, qui est très réfléchie et tente d'aborder un problème très fondamental. Il existe une réponse, même s'il est difficile de l'atteindre et qu'il n'y a peut-être pas de consensus.
0 votes
L'héritage est un cas limite bizarre de composition où l'objet interne ne changera jamais, et où l'objet externe doit exposer et déléguer toutes les méthodes de l'objet interne. En fin de compte, cela vous permet d'économiser quelques frappes de clavier dans ce scénario très spécifique, mais dans presque tous les cas, cela ne fait que créer des maux de tête. En règle générale, il faut l'éviter comme la peste.
1 votes
L'héritage est pas la seule façon d'utiliser le polymorphisme en c++. Vous avez également accès au polymorphisme statique en c++ par le biais des modèles. Je dirais que c'est la méthode préférée, et qu'elle fonctionne plus comme les interfaces, sauf qu'elles sont utilisées à la compilation plutôt qu'à l'exécution et ne nécessitent pas de déclaration formelle. Elles fonctionnent simplement lorsqu'un type correspondant au cas d'utilisation est fourni, sinon vous obtenez une erreur de compilation. Des concepts sont introduits pour aider à rendre l'interfaçage plus formel et moins dépendant des détails de mise en œuvre.