Il existe deux approches fondamentales pour combiner des objets entre eux :
- Le premier est Héritage . Comme vous l'avez déjà identifié, les limites de l'héritage signifient que vous ne pouvez pas faire ce dont vous avez besoin ici.
- Le second est Composition . Puisque l'héritage a échoué, vous devez utiliser la composition.
Le principe de fonctionnement est le suivant : vous disposez d'un objet Animal. Dans cet objet, vous ajoutez ensuite d'autres objets qui donnent les propriétés et les comportements dont vous avez besoin.
Par exemple :
-
Oiseau étend Animal met en œuvre IFlier
-
Cheval étend Animal met en œuvre IHerbivore, IQuadruped
-
Pegasus étend Animal met en œuvre IHerbivore, IQuadruped, IFlier
Maintenant IFlier
ressemble juste à ça :
interface IFlier {
Flier getFlier();
}
Alors Bird
ressemble à ça :
class Bird extends Animal implements IFlier {
Flier flier = new Flier();
public Flier getFlier() { return flier; }
}
Maintenant vous avez tous les avantages de l'héritage. Vous pouvez réutiliser le code. Vous pouvez avoir une collection d'IFliers, et utiliser tous les autres avantages du polymorphisme, etc.
Toutefois, vous bénéficiez également de toute la souplesse de la composition. Vous pouvez appliquer autant d'interfaces différentes et de classes de support composites que vous le souhaitez à chaque type d'objet Animal
- avec autant de contrôle que nécessaire sur la façon dont chaque bit est configuré.
Stratégie Pattern approche alternative de la composition
Une approche alternative, en fonction de ce que vous faites et de la manière dont vous le faites, est de faire en sorte que le Animal
La classe de base contient une collection interne pour conserver la liste des différents comportements. Dans ce cas, vous finissez par utiliser quelque chose de plus proche du Strategy Pattern. Cela présente des avantages en termes de simplification du code (par exemple Horse
n'a pas besoin de savoir quoi que ce soit sur Quadruped
o Herbivore
) mais si vous n'adoptez pas également l'approche par interface, vous perdez une grande partie des avantages du polymorphisme, etc.
7 votes
Je pense que vous pouvez créer manuellement les classes et les stocker comme membres (composition au lieu d'héritage). Avec le Proxy ( docs.oracle.com/javase/7/docs/api/java/lang/reflect/Proxy.html ), cela pourrait être une option, bien que vous ayez également besoin des interfaces.
0 votes
J'aime la solution de @GáborBakos, mais le seul inconvénient est qu'il ne peut pas avoir un type de référence générique.
4 votes
@RAM alors il ne devrait pas étendre Bird mais plutôt avoir un comportement qui lui permettra de prendre un vol :D problème résolu
11 votes
Exactement. Que diriez-vous d'une interface CanFly. :-)
28 votes
Je pense que c'est la mauvaise approche. Vous avez des animaux - Chevaux, Oiseaux. Et vous avez des propriétés - Volant, Carnivore. Un Pegasus n'est pas un HorseBird, c'est un cheval qui peut voler. Les propriétés devraient être des interfaces. Ainsi,
public class Pegasus extends Horse implements Flying
.12 votes
Je comprends pourquoi vous pensez que c'est mal et que cela n'adhère pas aux règles de la biologie et j'apprécie votre inquiétude, mais en ce qui concerne le programme que je dois construire, qui a en fait à voir avec les banques, c'était la meilleure approche pour moi. Comme je ne voulais pas poster mes problèmes réels, car cela irait à l'encontre des règles, j'ai un peu modifié l'exemple. Merci quand même...
2 votes
@Sheli Java 8 autorisera les interfaces avec des méthodes par défaut, ce qui permettra un type limité d'héritage multiple. Java 8 sortira à la mi-mars.
2 votes
Un meilleur exemple de vie réelle serait un enfant qui a une mère et un père, les deux étendant l'individu avec des attributs différents, alors vous pouvez hériter des deux, d'un mélange ou d'un seul d'entre eux (comme les attributs du sexe/comportement/Impl).