Java Héritage Multiple
Dans une tentative de comprendre pleinement comment résoudre Java héritage multiple problèmes que j'ai une question classique que j'ai besoin de clarifier.
Permet de dire que j'ai la classe Animal
cela a des sous-classes Bird
et Horse
et j'ai besoin de faire une classe Pegasus
qui s'étend de Bird
et Horse
depuis Pegasus
est à la fois un oiseau et un cheval.
Je pense que c'est le classique de diamant de problème. De ce que je peux comprendre la manière classique pour résoudre ce problème est de faire la Animal
, Bird
et Horse
classes d'interfaces et de mettre en œuvre Pegasus
d'eux.
Je me demandais si il y avait une autre façon de résoudre le problème en ce qui me permet encore de créer des objets pour les oiseaux et les chevaux. Si il y avait un moyen pour être en mesure de créer des animaux aussi, ce serait super, mais pas nécessaire.
- Je pense que vous pouvez créer manuellement les classes et de les stocker en tant que membres (composition à la place de l'héritage). Avec le Proxy (docs.oracle.com/javase/7/docs/api/java/lang/reflect/Proxy.html) cette classe pourrait être une option, mais vous aurez besoin d'interfaces trop.
- J'aime @GáborBakos solution, mais le seul inconvénient est qu'il ne peut pas avoir une référence générique de type.
- ensuite, il ne devrait pas s'étendre Oiseau plutôt avoir un comportement qui va lui permettre de prendre un vol. 😀 le problème est résolu
- Exactement. Comment sur une interface CanFly. 🙂
- Je pense que c'est la mauvaise approche. Vous avez des animaux - Chevaux, Oiseaux. Et vous avez propriétés de Vol, Carnivore. Une Pegasus n'est pas un HorseBird c'est un Cheval qui peut voler. Les propriétés doivent dans les interfaces. Donc
public class Pegasus extends Horse implements Flying
. - Je comprends pourquoi vous pensez que c'est mal et de ne pas respecter les règles de la biologie et de la comprenons votre inquiétude, mais en ce qui concerne le programme, j'ai besoin de construire qui a effectivement à voir avec les banques c'était la meilleure approche pour moi. Comme je n'ai pas envie de poster mon problème car cela serait contraire aux règles que j'ai changé l'exemple un peu. Merci bien...
- Java 8 permettra aux interfaces avec les méthodes par défaut, cela permettra une limité de l'héritage multiple. Java 8 est la version la mi-mars
- Un meilleur aper llife exemple serait de l'enfant qui a de père et de mère, à la fois l'extension de personne avec des attributs différents, alors vous pouvez hériter à la fois, un mélange ou un seul d'entre eux (comme le sexe attributs/comportement/Impl)
Vous devez vous connecter pour publier un commentaire.
Vous pouvez créer des interfaces pour les classes d'animaux (classe dans le sens biologique), comme
public interface Equidae
pour les chevaux et lespublic interface Avialae
pour les oiseaux (je ne suis pas biologiste, de sorte que les conditions trompe peut-être).Alors vous pouvez toujours créer un
et
et aussi
L'ajout de commentaires:
Afin de réduire les répétitions de code, vous pouvez créer une classe abstraite qui contient la plupart des communes code des animaux que vous souhaitez mettre en place.
Mise à jour
Je voudrais ajouter un plus de détail. Comme Brian remarques, c'est quelque chose que l'OP savait déjà.
Cependant, je tiens à souligner, que je suggère pour contourner le "multi-héritage" problème avec les interfaces et que je ne recommande pas d'utiliser des interfaces qui représentent déjà un type concret (comme les Oiseaux), mais plus d'un comportement (d'autres parlent de canard-typage, ce qui est bien aussi, mais je veux dire simplement: l'biologique de la classe des oiseaux, Avialae). Aussi, je ne recommande pas d'utiliser l'interface de noms commençant par un "I", comme
IBird
, qui ne dit rien au sujet de pourquoi vous avez besoin d'une interface. C'est la différence à la question: construire la hiérarchie d'héritage de l'utilisation d'interfaces, l'utilisation de classes abstraites lorsque c'est utile, la mise en place de classes nécessaires et à utiliser la délégation, le cas échéant.AbstractHorse
, qui peut également être utilisé pour construire des Zèbres ou des autres chevaux comme des animaux.AbstractEquidae
serait plus adapté queAbstractHorse
. Il serait étrange d'avoir un zèbre étendre un résumé de cheval. Belle réponse, par la manière.Duck
classe de mise en œuvre deAvialae
, trop?Il existe deux approches fondamentales de combiner des objets entre eux:
La façon dont cela fonctionne est que vous avez un Animal de l'objet. Dans cet objet, vous pouvez ensuite ajouter d'autres objets qui donnent les propriétés et les comportements que vous avez besoin.
Par exemple:
Maintenant
IFlier
ressemble à ceci:Donc
Bird
ressemble à ceci:Maintenant vous avez tous les avantages de l'Héritage. Vous pouvez ré-utiliser le code. Vous pouvez avoir une collection de IFliers, et peut utiliser toutes les autres avantages de polymorphisme, etc.
Cependant, vous avez également la flexibilité de la Composition. Vous pouvez demander que de nombreuses interfaces et composites support de la classe que vous le souhaitez à chaque type de
Animal
- avec autant de contrôle que vous avez besoin sur la façon dont chaque bit est mis en place.Modèle de stratégie approche alternative à la composition
Une approche alternative en fonction de ce que et comment vous faites, c'est d'avoir le
Animal
de la classe de base contient un interne de collecte de garder une liste de comportements différents. Dans ce cas, vous vous retrouvez à l'aide de quelque chose de plus pour le Modèle de Stratégie. Qui donne des avantages en termes de simplification du code (par exempleHorse
n'a pas besoin de savoir quelque chose au sujet deQuadruped
ouHerbivore
), mais si vous n'avez pas également faire l'approche de l'interface vous perdez beaucoup de les avantages de polymorphisme, etc.getFlier()
doit être réimplémentée pour chaque espèce d'oiseau.<T>T getComponent(Class<T>clazz)
méthode qui renvoie une composante correspondant à la classe spécifiée à partir d'un interne de la collection de composants.MathsTeacher
etEnglishTeacher
les deux hériterTeacher
,ChemicalEngineer
,MaterialsEngineer
etc hériterEngineer
.Teacher
etEngineer
à la fois de mettre en œuvreComponent
. LePerson
n'a alors qu'une liste deComponent
s, et vous pouvez leur donner le droitComponent
s pour quePerson
. c'est à direperson.getComponent(Teacher.class)
,person.getComponent(MathsTeacher.class)
, etc.J'ai une idée stupide:
interface
héritage de lui donner le code approprié contrat. Java 8 présentera une autre façon de résoudre ce rare--bien--problème en fournissant des méthodes par défaut dansinterface
s, mais vous limitant pas accès aux champs (comme c'est uninterface
).Puis-je suggérer le concept de En tapant Duck?
Plus probable que vous ont tendance à faire la Pegasus de prolonger un Oiseau, un Cheval, de l'interface, mais le duck-typing fait suggère que vous devriez plutôt hériter comportement. Comme déjà dit dans les commentaires, un pegasus n'est pas un oiseau, mais il peut voler. Si votre Pegasus devrait plutôt hériter d'une
Flyable
de l'interface et permet de dire unGallopable
-interface.Ce genre de concept est utilisé dans l' Modèle De Stratégie. L'exemple donné en fait vous montre comment faire un canard hérite de la
FlyBehaviour
etQuackBehaviour
et encore il peut y avoir des canards, par exemple, laRubberDuck
, qui ne peuvent pas voler. Ils auraient également fait l'Duck
étendre unBird
de classe, mais ensuite, ils auraient un peu de souplesse, parce que chaqueDuck
serait capable de voler, même les plus pauvresRubberDuck
.Techniquement parlant, vous ne pouvez étendre une classe à la fois et d'implémenter plusieurs interfaces, mais lors de la pose des mains sur l'ingénierie du logiciel, je préfère suggérer un problème spécifique de la solution généralement pas de réponse. Par ailleurs, il est bon OO pratique, pas d'étendre les classes de béton/seulement d'étendre les classes abstraites pour éviter les comportement de l'héritage - il n'y a pas une telle chose comme un "animal" et pas de l'utilisation de l'animal objet, mais seulement en béton animaux.
Dans Java 8, qui est encore en phase de développement, en date de février 2014, vous pouvez utiliser méthodes par défaut pour atteindre une sorte de C++-comme l'héritage multiple.
Vous pourriez aussi avoir un coup d'oeil à ce tutoriel qui montre quelques exemples qui devrait être plus facile de commencer à travailler avec de la documentation officielle.
Il est sûr de garder un cheval dans une écurie avec une demi la porte, comme un cheval ne peut pas obtenir plus d'un demi-porte. J'ai donc l'installation d'un cheval de service de logement qui accepte n'importe quel élément de type cheval et le met dans une étable avec une demi la porte.
Donc, c'est un cheval comme animal qui peut même voler un cheval?
Je pensais beaucoup au sujet de l'héritage multiple, mais maintenant que j'ai été la programmation depuis plus de 15 ans, je n'ai plus de soins sur l'implémentation de l'héritage multiple.
Plus souvent que pas, quand j'ai essayé de composer avec un design orienté vers l'héritage multiple, je dois venir plus tard à la libération que j'ai dû manquer compris le domaine du problème.
OU
Java ne dispose pas d'un héritage Multiple problème, puisqu'il n'a pas l'héritage multiple. C'est par la conception, dans le but de résoudre le vrai problème de l'héritage multiple (Le diamant problème).
Il existe différentes stratégies pour atténuer le problème. La partie la plus immédiatement réalisable étant l'objet Composite de Pavel suggère (essentiellement la façon dont C++ gère). Je ne sais pas si l'héritage multiple via C3 linéarisation (ou similaire) est sur les cartes de Java avenir, mais j'en doute.
Si votre question est de savoir académique, puis la bonne solution, c'est que l'Oiseau et le Cheval sont plus concrètes, et il est faux de supposer que, Pegasus est tout simplement un Oiseau, un Cheval, des combinés. Il serait plus exact de dire qu'un Pegasus a certaines propriétés intrinsèques en commun avec les Oiseaux et les Chevaux (c'est qu'ils ont peut-être des ancêtres communs). Cela peut être suffisamment modélisé comme Moritz réponse précise.
Je pense que tout dépend de vos besoins, et comment votre animal de classes sont à utiliser dans votre code.
Si vous voulez être en mesure de faire usage de méthodes et fonctions de votre Cheval et l'Oiseau implémentations à l'intérieur de votre Pegasus classe, alors vous pourriez mettre en œuvre Pegasus comme un composition d'un Oiseau et d'un Cheval:
Une autre possibilité est d'utiliser un L'Entité Composant De Système D' au lieu de l'héritage de la définition de vos animaux. Bien sûr, cela signifie, que vous n'aurez pas de personne Java classes des animaux, mais ils ne sont définies que par leurs composants.
De pseudo-code d'une Entité Composant de Système d'approche pourrait ressembler à ceci:
vous pouvez avoir une interface hiérarchie, puis d'étendre vos classes à partir de la sélection des interfaces :
puis définir vos classes nécessaires, par extension d'une interface spécifique :
IBird
etIHorse
devrait mettre en œuvreIAnimal
au lieu deAnimal
Euh, votre classe peut être la sous-classe pour seulement 1 d'autres, mais encore, vous pouvez avoir autant d'interfaces implémentées, comme vous le souhaitez.
Un Pegasus est en fait un cheval (c'est un cas particulier d'un cheval), qui est capable de voler (qui est la "compétence" de cette spéciale de cheval). D'autre part, vous pouvez dire, le Pegasus est un oiseau, qui est capable de marcher et est 4legged - tout dépend comment il est plus facile pour vous d'écrire le code.
Comme dans votre cas vous pouvez dire:
Interfaces ne pas simuler l'héritage multiple. Java créateurs considéré comme l'héritage multiple mal, donc il n'y a pas une telle chose en Java.
Si vous souhaitez combiner la fonctionnalité de deux classes en une seule utilisation de l'objet de la composition. I. e.
Et si vous souhaitez exposer certaines méthodes, de les définir et de les laisser déléguer l'appel à la manette correspondante.
Ici interfaces peut être pratique si
Component1
implémente l'interfaceInterface1
etComponent2
implémenteInterface2
, vous pouvez définirDe sorte que vous pouvez utiliser des objets de façon interchangeable, lorsque le contexte le permet.
Donc, à mon point de vue, vous ne pouvez pas obtenir dans le diamant problème.
Que vous serez déjà au courant, l'héritage multiple de classes en Java n'est pas possible, mais c'est possible avec les interfaces. Vous pouvez aussi envisager d'utiliser la composition motif de conception.
J'ai écrit un article très complet sur la composition il y a quelques années...
https://codereview.stackexchange.com/questions/14542/multiple-inheritance-and-composition-with-java-and-c-updated
Regardez ci-dessous un exemple pour mieux comprendre
Quand Utiliser le Pattern Décorateur?
Pour réduire la complexité et de simplifier la langue, l'héritage multiple n'est pas prise en charge par java.
Envisager un scénario où A, B et C sont trois classes. La classe C hérite des classes A et B. Si des classes A et B ont la même méthode et vous appelez cela de l'enfant objet de classe, il y aura de l'ambiguïté à l'appel de la méthode A ou B de classe.
Depuis le moment de la compilation les erreurs sont mieux que d'erreurs à l'exécution, java rend erreur de compilation si vous héritez de 2 classes. Donc, si vous avez la même méthode ou différents, il y aura erreur de compilation maintenant.
Pour résoudre le problème de l'héritage multiple en Java → interface est utilisée
J2EE (JAVA de noyau) Notes Par M. K. V. R Page 51