Menu
CoddyTech

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