Menu
Coddy logo textTech

Composition ou héritage

Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy. Leçon 82 sur 110.

Vous avez appris que l'héritage crée une relation « est-un » — un Dog est un Animal. Mais il existe une autre approche puissante : la composition, qui crée une relation « a-un ». Au lieu d'hériter d'un comportement, une classe contient des instances d'autres classes et leur délègue le travail.

Considérez une classe Car. Avec l'héritage, vous pourriez essayer d'étendre une classe Engine - mais une voiture n'est pas un moteur, elle a un moteur :

class Engine {
  void start() => print('Engine started');
}

class Car {
  final Engine _engine = Engine();  // Composition : Car A un Engine
  
  void start() {
    _engine.start();  // Déléguer au moteur
    print('Car is ready to drive');
  }
}

void main() {
  var car = Car();
  car.start();
}

L'avantage clé de la composition est la flexibilité. Avec l'héritage, vous êtes lié à une seule classe parente. Avec la composition, vous pouvez combiner plusieurs composants et même les échanger au moment de l'exécution :

class ElectricEngine {
  void start() => print('Electric motor humming');
}

class HybridCar {
  Engine? _gasEngine;
  ElectricEngine? _electricEngine;
  
  HybridCar({bool useElectric = false}) {
    if (useElectric) {
      _electricEngine = ElectricEngine();
    } else {
      _gasEngine = Engine();
    }
  }
}

Une directive courante est « favoriser la composition plutôt que l'héritage ». Utilisez l'héritage lorsqu'il existe une véritable relation « est un » (is-a) et que vous avez besoin de polymorphisme. Utilisez la composition lorsque vous souhaitez réutiliser un comportement sans couplage étroit, ou lorsqu'un objet a besoin de capacités provenant de plusieurs sources.

challenge icon

Défi

Facile

Construisons un système informatique en utilisant la composition ! Au lieu d’essayer de faire hériter un ordinateur de ses composants, tu vas créer des classes de composants séparées et les composer ensemble : comme un ordinateur possède un CPU et possède de la mémoire, ce n’est ni un CPU ni de la mémoire.

Tu organiseras ton code en trois fichiers :

  • components.dart : crée deux classes de composants qui représentent les pièces de l’ordinateur :
    • Une classe CPU avec un String brand et un double speedGHz. Inclus une méthode process() qui renvoie une chaîne de caractères : [brand] processing at [speedGHz]GHz
    • Une classe Memory avec un int sizeGB. Inclus une méthode load() qui renvoie une chaîne de caractères : Loading [sizeGB]GB of data
  • computer.dart : crée une classe Computer qui utilise la composition pour combiner les composants. Ton ordinateur doit :
    • Posséder un champ String name
    • Contenir une instance de CPU et une instance de Memory (composition : l’ordinateur POSSÈDE ces composants)
    • Accepter toutes les valeurs nécessaires via son constructeur afin de créer les deux composants en interne
    • Posséder une méthode boot() qui délègue le travail aux deux composants et affiche trois lignes : le nom de l’ordinateur suivi de starting..., puis le résultat de la méthode process du CPU, puis le résultat de la méthode load de la Memory
    • Posséder une méthode specs() qui renvoie une chaîne décrivant le système : [name]: [brand] [speedGHz]GHz, [sizeGB]GB RAM
  • main.dart : importe tes fichiers et montre la composition en action :
    • Crée un Computer nommé Workstation avec un CPU Intel fonctionnant à 3.5 GHz et 16 Go de mémoire
    • Appelle la méthode boot()
    • Affiche le résultat de specs()

Remarque que la classe Computer n’étend ni CPU ni Memory : elle les contient et leur délègue le travail. C’est la relation « possède-un » que crée la composition !

Résultat attendu :

Workstation starting...
Intel processing at 3.5GHz
Loading 16GB of data
Workstation: Intel 3.5GHz, 16GB RAM

Essayez vous-même

import 'computer.dart';

void main() {
  // TODO: Créer un Computer nommé "Workstation" avec :
  // - CPU Intel cadencé à 3.5 GHz
  // - 16 GB de mémoire

  // TODO: Appeler la méthode boot()

  // TODO: Afficher le résultat de specs()
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur Dart en ligne