web-dev-qa-db-fra.com

Différence entre l'héritage et la composition

Est-ce que la composition et l'héritage sont les mêmes?

166
gmhk

Ils sont absolument différents. L'héritage est une relation "est-une". La composition est un "has-a".

Vous faites la composition en ayant une instance d'une autre classe C comme champ de votre classe, au lieu d'étendre C. Java.util.Stack, qui étend actuellement Java.util.Vector, est un bon exemple où la composition aurait été bien meilleure que l'héritage. Ceci est maintenant considéré comme une erreur. Un vecteur de pile "is-NOT-a" "; vous ne devriez pas être autorisé à insérer et à supprimer des éléments de manière arbitraire. Cela aurait dû être la composition à la place.

Malheureusement, il est trop tard pour corriger cette erreur de conception, car la modification de la hiérarchie des héritages mettrait un terme à la compatibilité avec le code existant. Si Stack avait utilisé la composition au lieu de l'héritage, il peut toujours être modifié pour utiliser une autre structure de données sans violer l'API.

Je recommande fortement le livre de Josh Bloch Effective Java 2nd Edition

  • Point 16: Favoriser la composition par rapport à l'héritage
  • Rubrique 17: Concevoir et documenter en héritage ou bien l’interdire

Une bonne conception orientée objet ne consiste pas à étendre librement les classes existantes. Votre premier instinct devrait être de composer à la place.


Voir également:

261

Composition signifie HAS A
Héritage signifie IS A

Example: Voiture a un Moteur et voiture est un Automobile

En programmation, ceci 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.
}
170
codaddict

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 il ressort clairement du code ci-dessus, la classe Y a un couplage très fort avec la classe X. Si quelque chose change dans la super-classe X, Y peut se briser de manière spectaculaire. Supposons qu'à l'avenir, la classe X implémente une méthode de travail avec une signature ci-dessous

public int work(){
}

Le changement est effectué en classe X mais rendra la classe Y non compilable. SO Ce type de dépendance peut atteindre n'importe quel niveau et peut être très dangereux. Chaque fois que la superclasse peut ne pas avoir une visibilité complète sur le code dans toutes ses sous-classes, il est possible que la sous-classe continue de noter ce qui se passe dans la super-classe 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();
    }
}

Nous créons ici une référence de classe X dans la classe Y et invoquons une méthode de classe X en créant une instance de classe X . Maintenant, tout ce couplage fort a disparu. La superclasse et la sous-classe sont hautement indépendantes l'une de l'autre. Les classes peuvent librement effectuer des modifications dangereuses en cas d'héritage.

2) Deuxième très bon avantage de la composition en ce sens qu'il 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 utilisant la référence r, je peux appeler des méthodes de la classe X aussi bien que de la classe Y. Cette flexibilité n'a jamais existé en 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 être facilement simulé en utilisant certaines données de test et toutes les méthodes peuvent être facilement testées. Ce n'était pas du tout possible en héritage, car vous dépendiez beaucoup de la superclasse pour obtenir l'état de l'instance et exécuter une méthode.

4) Une autre bonne raison d'éviter l'héritage est que Java ne supporte pas 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 : 

  1. 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 

  2. 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. 

27
Manoj Kumar Saini

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. 

Interface implémentation est une forme d'héritage ... lorsque vous implémentez une interface, vous n'héritez pas seulement de toutes les constantes, vous engagez votre objet à être du type spécifié par l'interface; c'est toujours une relation "est-une". Si une voiture implémente Remplissable, la voiture "est-un" Remplissable, et peut être utilisée dans votre code partout où vous utiliseriez un Remplissable .

La composition est fondamentalement différente de l'héritage. Lorsque vous utilisez la composition, vous établissez une relation "a-a" entre deux objets, contrairement à la relation "est-a" que vous établissez lorsque vous utilisez l'héritage}. 

Ainsi, à partir des exemples de voiture dans les autres questions, si je voulais dire qu'un réservoir d'essence "has-a", j'utiliserais la composition, comme suit:

public class Car {

private GasTank myCarsGasTank;

}

Espérons que cela dissipe tout malentendu.

17
Kris

Héritage fait ressortir IS-A relation. Composition fait apparaître relation HAS-A . Le modèle de stratégie explique que Composition doit être utilisé dans les cas où il existe des familles d'algorithmes définissant un comportement particulier.
L'exemple classique étant une classe de canard qui implémente 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 volereg:

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 y avait eu héritage, nous aurions deux classes d'oiseaux différentes qui mettront en œuvre la fonction mouche à maintes reprises. Donc, l'héritage et la composition sont complètement différents.

14
frictionlesspulley

La composition est juste comme il semble - vous créez un objet en branchant des parties.

EDITle reste de cette réponse repose par erreur sur le principe suivant.
.__ Ceci est accompli avec les interfaces.
Par exemple, en utilisant l'exemple Car ci-dessus,

Car implements iDrivable, iUsesFuel, iProtectsOccupants
Motorbike implements iDrivable, iUsesFuel, iShortcutThroughTraffic
House implements iProtectsOccupants
Generator implements iUsesFuel

Donc, avec quelques composants théoriques standard, vous pouvez construire votre objet. C'est ensuite à vous de déterminer comment une House protège ses occupants et comment un 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 substituez les différents bits que vous souhaitez modifier.

Par exemple, MotorVehicle peut venir avec une méthode Fuelable et une méthode Drive. Vous pouvez laisser la méthode Fuel telle quelle car il est identique de remplir une moto et une voiture, mais vous pouvez remplacer la méthode Drive car la moto conduit très différemment d'une Car.

Avec l'héritage, certaines classes sont déjà complètement implémentées et d'autres ont des méthodes que vous devez forcer. Avec la composition, rien ne vous est donné. (mais vous pouvez implémenter les interfaces en appelant des méthodes dans d'autres classes s'il y a quelque chose qui traîne).

La composition est considérée comme plus flexible, car si vous utilisez une méthode telle que iUsesFuel, vous pouvez avoir une méthode ailleurs (une autre classe, un autre projet) qui se préoccupe uniquement de la gestion d'objets pouvant être alimentés, qu'il s'agisse d'une voiture ou non. bateau, réchaud, barbecue, etc. Les interfaces exigent que les classes qui disent implémenter cette interface aient les méthodes qui la régissent. 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();
   }

Étrange exemple, mais cela montre que cette méthode ne tient pas compte de ce qu'elle est en train de remplir, car l'objet implémente iUsesFuel, il peut être rempli. Fin de l'histoire.

Si vous utilisiez plutôt Héritage, vous auriez besoin de différentes méthodes FillHerUp pour traiter MotorVehicles et Barbecues, à moins que vous n'ayez un objet de base assez étrange "ObjectThatUsesFuel" à hériter.

7

La composition et l'héritage sont-ils les mêmes?

Ils ne sont pas pareils. 

Composition : Il permet à un groupe d'objets d'être traité de la même manière qu'une instance unique d'un objet. Le but d'un composite est de "composer" des objets dans des arborescences de manière à représenter des hiérarchies partielles

Héritage : Une classe hérite des champs et des méthodes de toutes ses super-classes, qu'ils soient directs ou indirects. Une sous-classe peut remplacer les méthodes dont elle hérite ou masquer des champs ou des méthodes dont elle hérite.

Si je veux implémenter le modèle de composition, comment puis-je le faire en Java?

Wikipedia article est assez bon pour implémenter un motif composite en Java.

 enter image description here

{PARTICIPANTS CL&EACUTE;S:}

Composant:

  1. L'abstraction est-elle pour tous les composants, y compris ceux composites?
  2. Déclare l'interface pour les objets de la composition

Feuille:

  1. Représente les objets feuille dans la composition
  2. Implémente toutes les méthodes Component

Composite:

  1. Représente un composant composite (composant ayant des enfants)
  2. Implémente des méthodes pour manipuler les enfants
  3. Implémente toutes les méthodes Component, généralement en les déléguant à ses enfants

Exemple de code pour comprendre le motif 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());
    }

}

sortie:

Car name:Innova
Car parts:DiselEngine Trunk Body
Car price:37000.0

Explication:

  1. Part est une feuille
  2. Car contient de nombreuses pièces
  3. Différents Pièces de la voiture ont été ajoutés à Car
  4. Le prix de {VOITURE} = somme de (Prix de chaque Pièce)

Reportez-vous à la question ci-dessous pour connaître les avantages et les inconvénients de la composition et de l'héritage.

Préfère la composition à l'héritage?

5
Ravindra babu

comme autre exemple, considérons une classe de voiture, ce serait un bon usage de la composition, une voiture "aurait" un moteur, une transmission, des pneus, des sièges, etc. Elle n’étendrait aucune de ces classes.

4
BlackICE

En mots simples, l'agrégation signifie avoir 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 exister sans l'existence d'un objet conteneur, il est appelé composition. Exemple: une classe contient des étudiants. Un étudiant ne peut 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 obtenue par agrégation quand il n’existe pas de relation

Héritage

L'héritage est une relation parent-enfant L'héritage signifie: c'est une relation

L'héritage en Java est un mécanisme dans lequel un objet acquiert toutes les propriétés et tous les comportements de l'objet parent.

Utilisation de l'héritage dans Java 1 Réutilisation du code 2 Ajoutez une fonctionnalité supplémentaire dans la classe enfant ainsi qu'une méthode prioritaire (afin de réaliser le polymorphisme d'exécution).

3
Keshav Gera

Héritage entre deux classes, où une classe étend une autre classe établit une relation " IS A ". 

Composition à l’autre extrémité contient une instance d’une autre classe de votre classe qui établit une relation "A une relation". Composition en Java est utile car il facilite techniquement l’héritage multiple.

3
John Wilson

La composition est où quelque chose est composé de différentes parties et il y a une relation forte avec ces parties. Si la partie principale meurt, les autres meurent aussi, ils ne peuvent pas avoir une vie propre. Un exemple approximatif est le corps humain. Enlevez le cœur et toutes les autres parties meurent.

L'héritage est l'endroit où vous prenez simplement quelque chose qui existe déjà et utilisez-le. Il n'y a pas de relation forte. Une personne peut hériter de la propriété de son père, mais elle peut s'en passer. 

Je ne connais pas Java, je ne peux donc pas donner d'exemple, mais je peux fournir une explication des concepts.

2
Robert Rocha

Bien que Héritage et Composition offrent des possibilités de réutilisation du code, la principale différence entre Composition et Héritage en Java est que Composition permet la réutilisation du code sans l'extension, mais pour Héritage, vous devez étendre la classe pour toute réutilisation du code ou des fonctionnalités. Une autre différence qui découle de ce fait est qu’en utilisant Composition, vous pouvez réutiliser du code même pour une classe finale qui n’est pas extensible, mais Inheritance ne peut pas réutiliser du code dans de tels cas. De plus, en utilisant Composition, vous pouvez réutiliser le code de nombreuses classes car elles ne sont déclarées que comme variables membres, mais avec Héritage, vous ne pouvez réutiliser le code que d'une 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 toujours préférez la composition à l'héritage en Java, ce n'est pas juste moi mais même - Joshua Bloch a suggéré dans son livre

2
Nitin Pawar

Je pense que cet exemple explique clairement les différences entre héritage et 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 inheritance, une modification de la superclasse peut entraîner des problèmes dans la classe dérivée, qui en hérite.

Vous pouvez également y voir la différence de représentation lorsque vous utilisez un langage UML pour l'héritage ou la composition.

http://www.javaworld.com/article/2076814/core-Java/inheritance-versus-composition--which-one-should-you-choose-.html

1
aunte

Héritage Vs Composition.

Les héritages et la composition sont tous deux utilisés pour réutiliser et étendre le comportement de classe. 

Les héritages utilisés principalement dans un modèle de programmation d'algorithme familial tel que le type de relation IS-A signifie un type d'objet similaire. Exemple.

  1. Duster est une voiture 
  2. Safari est une voiture

Ce sont la famille de voitures.

La composition représente la relation HAS-A. Elle montre la capacité d’un objet tel que Duster à cinq vitesses, Safari à quatre engrenages, etc. Chaque fois que nous devons étendre la capacité d’une classe existante, nous utilisons la composition. Exemple nous avons besoin pour ajouter un autre engrenage dans l'objet Duster, nous devons créer un autre objet engrenage et le composer pour cet objet.

Nous ne devrions pas apporter de modifications à la classe de base avant que/à moins que toutes les classes dérivées n’aient besoin de ces fonctionnalités. Pour ce scénario, nous devrions utiliser Composition.Such

classe A dérivée par classe B

Classe A Dérivée par Classe C

Classe A Dérivée par Classe D.

Lorsque nous ajoutons une fonctionnalité de la classe A, elle est disponible pour toutes les sous-classes, même lorsque les classes C et D ne l'exigent pas. Pour ce scénario, nous devons créer une classe distincte pour ces fonctionnalités et la composer en fonction de 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");
                       }
                   }
1
Sheo Dayal Singh

Héritage signifie réutiliser toutes les fonctionnalités 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 intégrale à 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 à une autre classe. composition, c'est déclarer 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. 

0
Vikas Kapadiya

Composition signifie créer un objet dans 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, il s'agit de la classe précédente avec la fonctionnalité étendue. Cela signifie que cette nouvelle classe est l'ancienne classe avec certaines fonctionnalités étendues… .. Supposons que l'étudiant soit un étudiant mais que tous les étudiants sont humains. Donc, il y a une relation avec l'étudiant et l'homme. C'est l'héritage.

0
HM Nayem

Non, les deux sont différents. La composition suit la relation "HAS-A" et l'héritage la relation "IS-A". Le meilleur exemple de composition était le modèle stratégique.

0
Ranga Reddy

Compostion

  • est un moyen de combiner simple objets ou types de données en plusieurs complexes uns
  • Une relation de composition existe entre deux classes si le ou les champs d’une classe sont constitués d’une autre classe.
  • Appelé en tant que a-a relation

Héritage

  • En surface, l'héritage est un code réutiliser
  • nous pouvons étendre le code qui est déjà écrit de manière gérable.
  • L'héritage est plus, il prend en charge le polymorphisme au niveau de la langue!
  • Les informations sont gérables dans un ordre hiérarchique
  • Avec l'héritage, une nouvelle classe peut être dérivée des classes existantes en tant que bloc de construction
  • Nouvelle classe Propriétés et méthodes héritées de la classe existante
  • using étend et implements Keywords
  • Il existe une hiérarchie de classes (directe/indirecte/unique/multiple)
0
Malith Ileperuma