La composition et l'héritage sont-ils les mêmes? Si je veux implémenter le modèle de composition, comment puis-je le faire en Java?
La composition et l'héritage sont-ils les mêmes? Si je veux implémenter le modèle de composition, comment puis-je le faire en Java?
Réponses:
Ils sont absolument différents. L'héritage est une relation «est-une» . La composition est un "has-a" .
Vous faites de la composition en ayant une instance d'une autre classe C
comme champ de votre classe, au lieu de l'étendre C
. Un bon exemple où la composition aurait été bien meilleure que l'héritage java.util.Stack
, qui s'étend actuellement java.util.Vector
. Ceci est maintenant considéré comme une erreur. Un vecteur de pile "n'est-PAS-un" ; vous ne devez pas être autorisé à insérer et à supprimer des éléments arbitrairement. Cela aurait dû être de la composition à la place.
Malheureusement, il est trop tard pour corriger cette erreur de conception, car la modification de la hiérarchie d'héritage romprait maintenant la compatibilité avec le code existant. Si la Stack
composition avait été utilisée au lieu de l'héritage, elle peut toujours être modifiée pour utiliser une autre structure de données sans violer l'API .
Je recommande fortement le livre de Josh Bloch Effective Java 2nd Edition
Une bonne conception orientée objet ne consiste pas à étendre généreusement les classes existantes. Votre premier instinct devrait être de composer à la place.
Voir également:
Composition signifie HAS A
Héritage signifieIS A
Example
: La voiture a un moteur et la voiture est une automobile
Dans la programmation, cela est représenté comme:
class Engine {} // The Engine class.
class Automobile {} // Automobile class which is parent to Car class.
class Car extends Automobile { // Car is an Automobile, so Car class extends Automobile class.
private Engine engine; // Car has an Engine so, Car class has an instance of Engine class as its member.
}
:-/
type
champ de typeEnum
Comment l'héritage peut-il être dangereux?
Prenons un exemple
public class X{
public void do(){
}
}
Public Class Y extends X{
public void work(){
do();
}
}
1) Comme indiqué dans le code ci-dessus, la classe Y a un couplage très fort avec la classe X. Si quelque chose change dans la superclasse X, Y peut se briser de façon spectaculaire. Supposons qu'à l'avenir, la classe X implémente un travail de méthode avec la signature ci-dessous
public int work(){
}
Le changement se fait en classe X mais cela rendra la classe Y incompilable. Ce type de dépendance peut donc atteindre n'importe quel niveau et peut être très dangereux. Chaque fois que la superclasse peut ne pas avoir une visibilité complète pour coder dans toutes ses sous-classes et la sous-classe peut continuer à remarquer ce qui se passe dans la superclasse tout le temps. Nous devons donc éviter ce couplage fort et inutile.
Comment la composition résout-elle ce problème?
Voyons en révisant le même exemple
public class X{
public void do(){
}
}
Public Class Y{
X x = new X();
public void work(){
x.do();
}
}
Ici, nous créons la référence de la classe X dans la classe Y et invoquons la méthode de la classe X en créant une instance de la classe X. Maintenant, tout ce couplage fort a disparu. La superclasse et la sous-classe sont désormais très indépendantes l'une de l'autre. Les classes peuvent librement apporter des modifications dangereuses en situation successorale.
2) Deuxième très bon avantage de la composition en ce qu'elle offre une flexibilité d'appel de méthode, par exemple:
class X implements R
{}
class Y implements R
{}
public class Test{
R r;
}
Dans la classe Test en utilisant la référence r, je peux invoquer des méthodes de classe X ainsi que de classe Y. Cette flexibilité n'a jamais été là dans l'héritage
3) Un autre grand avantage: les tests unitaires
public class X {
public void do(){
}
}
Public Class Y {
X x = new X();
public void work(){
x.do();
}
}
Dans l'exemple ci-dessus, si l'état de l'instance x n'est pas connu, il peut facilement être simulé en utilisant certaines données de test et toutes les méthodes peuvent être facilement testées. Cela n'était pas possible du tout en héritage car vous dépendiez fortement de la superclasse pour obtenir l'état d'instance et exécuter n'importe quelle méthode.
4) Une autre bonne raison pour laquelle nous devrions éviter l'héritage est que Java ne prend pas en charge l'héritage multiple.
Prenons un exemple pour comprendre ceci:
Public class Transaction {
Banking b;
public static void main(String a[])
{
b = new Deposit();
if(b.deposit()){
b = new Credit();
c.credit();
}
}
}
Bon à savoir :
la composition est facilement réalisée au moment de l'exécution tandis que l'héritage fournit ses fonctionnalités au moment de la compilation
la composition est également connue sous le nom de relation HAS-A et l'héritage est également connu sous le nom de relation IS-A
Prenez donc l'habitude de toujours préférer la composition à l'héritage pour diverses raisons ci-dessus.
La réponse donnée par @Michael Rodrigues n'est pas correcte (je m'excuse, je ne suis pas en mesure de commenter directement), et pourrait conduire à une certaine confusion.
L'implémentation d' une interface est une forme d'héritage ... lorsque vous implémentez une interface, vous héritez non seulement de toutes les constantes, vous engagez votre objet à être du type spécifié par l'interface; c'est toujours une relation « est-un ». Si une voiture implémente Fillable , la voiture " est un " Fillable , et peut être utilisée dans votre code partout où vous utiliseriez un Fillable .
La composition est fondamentalement différente de l'héritage. Lorsque vous utilisez la composition, vous établissez (comme le notent les autres réponses) une relation " has-a " entre deux objets, par opposition à la relation " is-a " que vous établissez lorsque vous utilisez l'héritage .
Donc, à partir des exemples de voitures dans les autres questions, si je voulais dire qu'une voiture a un réservoir d'essence, j'utiliserais la composition comme suit:
public class Car {
private GasTank myCarsGasTank;
}
Espérons que cela dissipe tout malentendu.
L'héritage fait ressortir IS-A relation . La composition fait ressortir la relation HAS-A . Le modèle de stratégie explique que la composition doit être utilisée dans les cas où il existe des familles d'algorithmes définissant un comportement particulier.
Exemple classique étant d'une classe de canard qui met en œuvre un comportement de vol.
public interface Flyable{
public void fly();
}
public class Duck {
Flyable fly;
public Duck(){
fly = new BackwardFlying();
}
}
Ainsi, nous pouvons avoir plusieurs classes qui implémentent le vol, par exemple:
public class BackwardFlying implements Flyable{
public void fly(){
Systemout.println("Flies backward ");
}
}
public class FastFlying implements Flyable{
public void fly(){
Systemout.println("Flies 100 miles/sec");
}
}
S'il avait été question d'héritage, nous aurions deux classes d'oiseaux différentes qui implémentent la fonction mouche à maintes reprises. L'héritage et la composition sont donc complètement différents.
La composition est exactement comme elle sonne - vous créez un objet en branchant des parties.
MODIFIER le reste de cette réponse est basé à tort sur la prémisse suivante.
Ceci est accompli avec des interfaces.
Par exemple, en utilisant l' Car
exemple ci-dessus,
Car implements iDrivable, iUsesFuel, iProtectsOccupants
Motorbike implements iDrivable, iUsesFuel, iShortcutThroughTraffic
House implements iProtectsOccupants
Generator implements iUsesFuel
Ainsi, avec quelques composants théoriques standard, vous pouvez construire votre objet. C'est alors à vous de déterminer comment a House
protège ses occupants et comment a Car
protège ses occupants.
L'héritage est comme l'inverse. Vous commencez avec un objet complet (ou semi-complet) et vous remplacez ou remplacez les différents bits que vous souhaitez modifier.
Par exemple, MotorVehicle
peut venir avec une Fuelable
méthode et une Drive
méthode. Vous pouvez laisser la méthode Fuel telle quelle, car c'est la même chose pour remplir une moto et une voiture, mais vous pouvez remplacer la Drive
méthode parce que la moto roule très différemment d'une a Car
.
Avec l'héritage, certaines classes sont déjà complètement implémentées, et d'autres ont des méthodes que vous êtes obligé de remplacer. Avec Composition, rien ne vous est donné. (mais vous pouvez implémenter les interfaces en appelant des méthodes dans d'autres classes s'il vous arrive d'avoir quelque chose autour).
La composition est considérée comme plus flexible, car si vous avez une méthode telle que iUsesFuel, vous pouvez avoir une méthode ailleurs (une autre classe, un autre projet) qui se soucie simplement de traiter avec des objets pouvant être alimentés, qu'il s'agisse d'une voiture, bateau, poêle, barbecue, etc. Les interfaces exigent que les classes qui disent qu'elles implémentent cette interface aient en fait les méthodes dont il s'agit. Par exemple,
iFuelable Interface:
void AddSomeFuel()
void UseSomeFuel()
int percentageFull()
alors vous pouvez avoir une méthode ailleurs
private void FillHerUp(iFuelable : objectToFill) {
Do while (objectToFill.percentageFull() <= 100) {
objectToFill.AddSomeFuel();
}
Exemple étrange, mais cela montre que cette méthode ne se soucie pas de ce qu'elle remplit, car l'objet implémente iUsesFuel
, il peut être rempli. Fin de l'histoire.
Si vous utilisiez l'héritage à la place, vous auriez besoin de différentes FillHerUp
méthodes pour traiter MotorVehicles
et Barbecues
, sauf si vous aviez un objet de base "ObjectThatUsesFuel" plutôt étrange dont vous devez hériter.
ThisCase
, et non en camelCase
. Par conséquent, il est préférable de nommer vos interfaces IDrivable
, etc. Vous pourriez ne pas avoir besoin du «I» si vous regroupez correctement toutes vos interfaces dans un package.
La composition et l'héritage sont-ils les mêmes?
Ce ne sont pas les mêmes.
Composition : il permet de traiter un groupe d'objets de la même manière qu'une seule instance d'un objet. L'intention d'un composite est de "composer" des objets en structures arborescentes pour représenter des hiérarchies partielles
Héritage : une classe hérite des champs et des méthodes de toutes ses superclasses, directes ou indirectes. Une sous-classe peut remplacer les méthodes dont elle hérite ou masquer les champs ou les méthodes dont elle hérite.
Si je veux implémenter le modèle de composition, comment puis-je le faire en Java?
L' article de Wikipédia est assez bon pour implémenter un modèle composite en java.
Participants clés:
Composant :
Feuille :
Composite :
Exemple de code pour comprendre le modèle composite :
import java.util.List;
import java.util.ArrayList;
interface Part{
public double getPrice();
public String getName();
}
class Engine implements Part{
String name;
double price;
public Engine(String name,double price){
this.name = name;
this.price = price;
}
public double getPrice(){
return price;
}
public String getName(){
return name;
}
}
class Trunk implements Part{
String name;
double price;
public Trunk(String name,double price){
this.name = name;
this.price = price;
}
public double getPrice(){
return price;
}
public String getName(){
return name;
}
}
class Body implements Part{
String name;
double price;
public Body(String name,double price){
this.name = name;
this.price = price;
}
public double getPrice(){
return price;
}
public String getName(){
return name;
}
}
class Car implements Part{
List<Part> parts;
String name;
public Car(String name){
this.name = name;
parts = new ArrayList<Part>();
}
public void addPart(Part part){
parts.add(part);
}
public String getName(){
return name;
}
public String getPartNames(){
StringBuilder sb = new StringBuilder();
for ( Part part: parts){
sb.append(part.getName()).append(" ");
}
return sb.toString();
}
public double getPrice(){
double price = 0;
for ( Part part: parts){
price += part.getPrice();
}
return price;
}
}
public class CompositeDemo{
public static void main(String args[]){
Part engine = new Engine("DiselEngine",15000);
Part trunk = new Trunk("Trunk",10000);
Part body = new Body("Body",12000);
Car car = new Car("Innova");
car.addPart(engine);
car.addPart(trunk);
car.addPart(body);
double price = car.getPrice();
System.out.println("Car name:"+car.getName());
System.out.println("Car parts:"+car.getPartNames());
System.out.println("Car price:"+car.getPrice());
}
}
production:
Car name:Innova
Car parts:DiselEngine Trunk Body
Car price:37000.0
Explication:
Référez-vous à la question ci-dessous pour les avantages et les inconvénients de la composition et de l'héritage.
comme autre exemple, considérons une classe de voitures, ce serait une bonne utilisation de la composition, une voiture "aurait" un moteur, une transmission, des pneus, des sièges, etc. Cela ne prolongerait aucune de ces classes.
La composition est l'endroit où quelque chose est composé de parties distinctes et il a une relation forte avec ces parties. Si la partie principale décède, les autres ne peuvent pas avoir leur propre vie. Un exemple grossier est le corps humain. Retirez le cœur et toutes les autres parties disparaissent.
L'héritage est l'endroit où vous prenez simplement quelque chose qui existe déjà et que vous l'utilisez. Il n'y a pas de relation solide. Une personne peut hériter de la succession de son père, mais elle peut s'en passer.
Je ne connais pas Java donc je ne peux pas donner d'exemple mais je peux donner une explication des concepts.
L'héritage entre deux classes, où une classe étend une autre classe établit une relation " EST A ".
La composition à l'autre extrémité contient une instance d'une autre classe dans votre classe établit une relation " A une ". La composition en java est utile car elle facilite techniquement l'héritage multiple.
Dans Simple Word, l'agrégation de mots signifie a une relation.
La composition est un cas particulier d'agrégation . De manière plus spécifique, une agrégation restreinte est appelée composition. Lorsqu'un objet contient l'autre objet, si l'objet contenu ne peut pas exister sans l'existence d'un objet conteneur, il est appelé composition. Exemple: une classe contient des élèves. Un étudiant ne peut pas exister sans classe. Il existe une composition entre la classe et les étudiants.
Pourquoi utiliser l'agrégation
Réutilisation du code
Quand utiliser l'agrégation
La réutilisation du code est également mieux réalisée par agrégation lorsqu'il n'y a pas de navire de relation
Héritage
L'héritage est une relation parent-enfant signifie que l'héritage est une relation
L'héritage en java est un mécanisme dans lequel un objet acquiert toutes les propriétés et les comportements de l'objet parent.
Utilisation de l'héritage dans Java 1 Code Reusability. 2 Ajoutez une fonctionnalité supplémentaire dans la classe enfant ainsi que la substitution de méthode (afin que le polymorphisme d'exécution puisse être atteint).
Bien que l'héritage et la composition fournissent la réutilisation du code, la principale différence entre la composition et l'héritage en Java est que la composition permet la réutilisation du code sans l'étendre, mais pour l'héritage, vous devez étendre la classe pour toute réutilisation du code ou des fonctionnalités. Une autre différence qui vient de ce fait est qu'en utilisant Composition, vous pouvez réutiliser du code même pour la classe finale qui n'est pas extensible, mais l'héritage ne peut pas réutiliser le code dans de tels cas. De plus, en utilisant Composition, vous pouvez réutiliser le code de nombreuses classes car elles sont déclarées comme une simple variable membre, mais avec l'héritage, vous pouvez réutiliser le code sous une seule classe car en Java, vous ne pouvez étendre qu'une seule classe, car l'héritage multiple n'est pas pris en charge en Java . Vous pouvez le faire en C ++ car une classe peut étendre plusieurs classes. BTW, vous devriez toujourspréfèrent la composition à l'héritage en Java , ce n'est pas seulement moi, mais même Joshua Bloch l' a suggéré dans son livre
Je pense que cet exemple explique clairement les différences entre l' héritage et la composition .
Dans cet exemple, le problème est résolu en utilisant l'héritage et la composition. L'auteur fait attention au fait que; dans l' héritage , un changement de superclasse peut provoquer des problèmes dans la classe dérivée, qui l'hérite.
Là, vous pouvez également voir la différence de représentation lorsque vous utilisez un UML pour l'héritage ou la composition.
Héritages Vs Composition.
Les héritages et la composition sont tous deux utilisés pour la réutilisation et l'extension du comportement de classe.
Les héritages principalement utilisés dans un modèle de programmation d'algorithmes familiaux tels que le type de relation IS-A signifient un type d'objet similaire. Exemple.
Ils appartiennent à la famille Car.
La composition représente le type de relation HAS-A. Elle montre la capacité d'un objet tel que Duster a cinq vitesses, Safari a quatre vitesses, etc. Chaque fois que nous devons étendre la capacité d'une classe existante, utilisez la composition. Exemple, nous devons ajouter un autre engrenage dans l'objet Duster, puis nous devons créer un autre objet engrenage et le composer dans l'objet Duster.
Nous ne devons pas apporter de modifications à la classe de base tant que / à moins que toutes les classes dérivées n'aient besoin de ces fonctionnalités. Pour ce scénario, nous devons utiliser Composition.
classe A dérivée de la classe B
Classe A dérivée de la classe C
Classe A dérivée de la classe D.
Lorsque nous ajoutons une fonctionnalité dans la classe A, elle est disponible pour toutes les sous-classes même lorsque les classes C et D ne nécessitent pas ces fonctionnalités.Pour ce scénario, nous devons créer une classe distincte pour ces fonctionnalités et la composer dans la classe requise ( voici la classe B).
Voici l'exemple:
// This is a base class
public abstract class Car
{
//Define prototype
public abstract void color();
public void Gear() {
Console.WriteLine("Car has a four Gear");
}
}
// Here is the use of inheritence
// This Desire class have four gears.
// But we need to add one more gear that is Neutral gear.
public class Desire : Car
{
Neutral obj = null;
public Desire()
{
// Here we are incorporating neutral gear(It is the use of composition).
// Now this class would have five gear.
obj = new Neutral();
obj.NeutralGear();
}
public override void color()
{
Console.WriteLine("This is a white color car");
}
}
// This Safari class have four gears and it is not required the neutral
// gear and hence we don't need to compose here.
public class Safari :Car{
public Safari()
{ }
public override void color()
{
Console.WriteLine("This is a red color car");
}
}
// This class represents the neutral gear and it would be used as a composition.
public class Neutral {
public void NeutralGear() {
Console.WriteLine("This is a Neutral Gear");
}
}
La composition signifie créer un objet à une classe qui a une relation avec cette classe particulière. Supposons que l'étudiant ait une relation avec les comptes;
Un héritage est, c'est la classe précédente avec la fonctionnalité étendue. Cela signifie que cette nouvelle classe est l'ancienne classe avec des fonctionnalités étendues. Supposons que l'étudiant soit étudiant mais que tous les étudiants soient humains. Il y a donc une relation avec l'étudiant et l'humain. C'est l'héritage.
Non, les deux sont différents. La composition suit la relation "HAS-A" et l'héritage suit la relation "IS-A". Le meilleur exemple de composition était le modèle stratégique.
L'héritage signifie la réutilisation de la fonctionnalité complète d'une classe, ici ma classe doit utiliser toutes les méthodes de la super classe et ma classe sera couplée de manière titrée avec la super classe et le code sera dupliqué dans les deux classes en cas d'héritage.
Mais nous pouvons surmonter tous ces problèmes lorsque nous utilisons la composition pour parler avec une autre classe. composition déclare un attribut d'une autre classe dans ma classe à laquelle nous voulons parler. et quelle fonctionnalité nous voulons de cette classe, nous pouvons obtenir en utilisant cet attribut.