"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > Composition vs héritage

Composition vs héritage

Publié le 2024-11-09
Parcourir:362

Composición vs Herencia

Introduction

L'héritage et la composition sont deux concepts fondamentaux de la programmation orientée objet (POO), mais ils sont utilisés différemment et ont des objectifs différents. L'objectif de cet article est de passer en revue ces objectifs et certains éléments à garder à l'esprit lors de leur choix.

Notions d'héritage

Lorsque nous réfléchissons à l'application de l'héritage dans nos conceptions, nous devons comprendre :

  • Définition : en héritage, une classe (appelée classe ou sous-classe dérivée) peut hériter des propriétés et des comportements d'une autre classe (appelée classe de base ou superclasse). La classe dérivée peut étendre ou modifier les fonctionnalités de la classe de base.
  • Relation : C'est une relation "est un" (est-un). Par exemple, si vous avez une classe « Véhicule » et une autre classe « Voiture », la classe « Voiture » ​​est une sous-classe de « Véhicule ».
  • Avantages : favorise la réutilisation du code et permet une extension facile des fonctionnalités.

Notions de composition

En revanche, si l'on pense composer des objets ensemble :

  • Définition : En composition, un objet contient d'autres objets et leur délègue une partie de ses fonctionnalités. Au lieu de l'héritage, une classe utilise des instances d'autres classes pour atteindre ses fonctionnalités.
  • Relation : il s'agit d'une relation "has-a". Par exemple, si vous avez une classe "Engine" et une classe "Car", la classe "Car" peut avoir un objet de classe "Engine".
  • Avantages : Plus de flexibilité et moins de couplage entre les classes. Les changements dans une classe n’affectent pas directement l’autre.

Pourquoi un concordat sur l'héritage ?

La question de savoir si la composition est meilleure que l'héritage ou vice versa est un sujet débattu dans la conception de logiciels. Les deux approches ont leurs avantages et leurs inconvénients, et le choix dépend du contexte et des exigences spécifiques du projet. Ici, je vais vous présenter un exemple où la composition peut être préférable à l'héritage.

Explorons un exemple en Java qui illustre comment la composition peut être préférable à l'héritage dans certains cas. Supposons que nous travaillions sur un système de traitement des commandes dans une boutique en ligne.

  • Approche successorale :

Tout d'abord, considérons une approche utilisant l'héritage pour représenter différents types de produits achetables, tels que les livres et les appareils électroniques :

// Clase base para productos
class Producto {
    String nombre;
    double precio;

    Producto(String nombre, double precio) {
        this.nombre = nombre;
        this.precio = precio;
    }

    void procesarPedido() {
        System.out.println("Procesando pedido para "   nombre);
    }
}

// Clase para productos electrónicos que hereda de Producto
class ProductoElectronico extends Producto {
    String modelo;

    ProductoElectronico(String nombre, double precio, String modelo) {
        super(nombre, precio);
        this.modelo = modelo;
    }
}

// Clase para libros que hereda de Producto
class Libro extends Producto {
    String autor;

    Libro(String nombre, double precio, String autor) {
        super(nombre, precio);
        this.autor = autor;
    }
}

Cette approche fonctionne, mais que se passe-t-il si vous devez introduire de nouveaux types de produits ou ajouter des fonctionnalités spécifiques pour certains types de produits ?

  • Concentrez-vous avec la composition :

Au lieu de nous fier entièrement à l'héritage, nous pourrions utiliser la composition pour gérer différents types de produits de manière plus flexible :

// Clase para productos
class Producto {
    String nombre;
    double precio;

    Producto(String nombre, double precio) {
        this.nombre = nombre;
        this.precio = precio;
    }

    void procesarPedido() {
        System.out.println("Procesando pedido para "   nombre);
    }
}

// Clase para productos electrónicos que utiliza composición
class ProductoElectronico {
    Producto producto;
    String modelo;

    ProductoElectronico(String nombre, double precio, String modelo) {
        this.producto = new Producto(nombre, precio);
        this.modelo = modelo;
    }

    // Puedes agregar lógica específica para productos electrónicos si es necesario
    void procesarPedidoEspecifico() {
        System.out.println("Procesando pedido específico para "   producto.nombre);
    }
}

// Clase para libros que utiliza composición
class Libro {
    Producto producto;
    String autor;

    Libro(String nombre, double precio, String autor) {
        this.producto = new Producto(nombre, precio);
        this.autor = autor;
    }

    // Puedes agregar lógica específica para libros si es necesario
    void procesarPedidoEspecifico() {
        System.out.println("Procesando pedido específico para "   producto.nombre);
    }
}

Dans cette approche, chaque type de produit possède une instance de la classe Product, permettant de partager une logique commune pour le traitement des commandes. De plus, chaque type de produit peut avoir sa propre logique spécifique à l'aide de méthodes telles que processSpecificOrder(). Cette conception est plus flexible et facilite l'introduction de nouveaux types de produits ou la modification de la logique spécifique au type sans affecter la hiérarchie d'héritage.

Quand appliquer l’héritage ?

Alors que le choix entre l'héritage et la composition dans la conception de logiciels dépend du contexte et des exigences spécifiques du problème que vous abordez. Voici quelques situations dans lesquelles vous pourriez considérer l’héritage comme une option plus appropriée que la composition :

  • Relation "est-un" : l'héritage est particulièrement approprié lorsqu'il existe une relation claire "est-un" entre les classes. Si une classe B est une version plus spécifique ou spécialisée d’une classe A, alors l’héritage a du sens. Par exemple, si vous avez une classe Vehicle et une classe Car, la relation « est-un » est claire, puisqu'une voiture est un type de véhicule.
class Vehiculo {
    // ...
}

class Automovil extends Vehiculo {
    // ...
}
  • Réutilisation du code : l'héritage permet la réutilisation du code, puisque la classe dérivée hérite des membres et des méthodes de la classe de base. Cela peut être bénéfique lorsqu'il existe une quantité importante de code commun entre des classes liées.
class Animal {
    void comer() {
        // Lógica común para comer
    }
}

class Perro extends Animal {
    void ladrar() {
        // Lógica específica para ladrar
    }
}
  • Polymorphisme : l'héritage est fondamental pour l'implémentation du polymorphisme, qui permet aux classes dérivées de fournir des implémentations spécifiques de méthodes héritées de la classe de base. Ceci est utile dans les scénarios où vous devez traiter uniformément les objets des classes dérivées.
class Figura {
    void dibujar() {
        // Lógica común para dibujar una figura
    }
}

class Circulo extends Figura {
    void dibujar() {
        // Lógica específica para dibujar un círculo
    }
}

class Cuadrado extends Figura {
    void dibujar() {
        // Lógica específica para dibujar un cuadrado
    }
}

  • Extensions de fonctionnalités : si vous étendez ou spécialisez des fonctionnalités existantes, l'héritage peut être plus naturel. Par exemple, si vous développez une bibliothèque et que vous fournissez une classe de base avec des fonctionnalités de base, les utilisateurs de votre bibliothèque peuvent dériver de cette classe de base pour étendre cette fonctionnalité.

Que se passe-t-il si nous faisons un mauvais héritage ?

Si nous continuons à évaluer les avantages et les inconvénients de l'héritage, l'un des problèmes pouvant découler d'un mauvais héritage est que nous violerions le principe de ségrégation des interfaces, qui stipule que les clients ne devraient pas être obligés de dépendre des interfaces qu'ils utilisent. pas utiliser. Si une interface est étendue de manière à inclure des méthodes qui ne sont pas pertinentes pour toutes les implémentations, les clients utilisant cette interface pourraient être obligés d'implémenter ou de dépendre de méthodes dont ils n'ont pas besoin, ce qui peut conduire à une conception moins propre et plus difficile. maintenir.

Conclusion

En résumé, l'héritage se concentre sur la relation « est un » et est utilisé pour modéliser les hiérarchies de classes, tandis que la composition se concentre sur la relation « a un » et est utilisée pour construire des objets complexes à partir d'autres objets plus simples. Les deux approches ont leurs cas d'utilisation spécifiques et sont choisies en fonction de la structure et de la nature des relations dans la conception du logiciel.

Déclaration de sortie Cet article est reproduit sur : https://dev.to/rlgino/composicion-vs-herencia-4664?1 En cas de violation, veuillez contacter [email protected] pour le supprimer.
Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3