Menu
Coddy logo textTech

Implémentation vs Extension

Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy — leçon 47 sur 110.

Maintenant que vous comprenez à la fois extends et implements, clarifions quand utiliser chacun d'eux.

Utilisez extends lorsque vous souhaitez hériter d'un comportement. Votre sous-classe obtient gratuitement tout le code du parent et peut s'appuyer dessus :

class Animal {
  void breathe() {
    print('Breathing...');
  }
}

class Dog extends Animal {
  void bark() {
    print('Woof!');
  }
}

void main() {
  var dog = Dog();
  dog.breathe();  // Hérité - fonctionne automatiquement
  dog.bark();
}

Utilisez implements lorsque vous voulez garantir une structure sans hériter de code. Vous devez écrire chaque méthode vous-même :

class Robot implements Animal {
  @override
  void breathe() {
    print('Ventilating circuits...');  // Implémentation complètement personnalisée
  }
}

La différence clé : extends dit « Je suis un type de ceci » tandis que implements dit « Je peux faire ce que ceci fait. » Un Dog est un Animal et respire de la même manière. Un Robot n'est pas un animal, mais il peut remplir le même contrat avec sa propre logique.

Rappelez-vous : vous ne pouvez étendre qu'une seule classe, mais vous pouvez implémenter plusieurs interfaces. Choisissez extends pour les véritables relations d'héritage, et implements lorsque vous avez besoin de flexibilité ou que vous souhaitez imposer un contrat sans partager les détails d'implémentation.

challenge icon

Défi

Facile

Construisons un système de travailleurs qui démontre quand utiliser extends par rapport à implements. Vous allez créer une classe de base pour les travailleurs, puis montrer les deux approches : une classe qui "est" véritablement un travailleur et hérite de son comportement, et une autre qui peut simplement "faire" ce qu'un travailleur fait, mais avec une logique complètement personnalisée.

Vous organiserez votre code dans deux fichiers :

  • worker.dart : Définissez votre hiérarchie de travailleurs ici :
    • Une classe Worker avec une propriété String name et un constructeur. Incluez une méthode work() qui affiche [name] is working... et une méthode takeBreak() qui affiche [name] takes a coffee break
    • Une classe OfficeWorker qui étend (extends) Worker. Ajoutez une propriété String department. Surchargez work() pour afficher [name] is typing reports in [department] mais conservez le comportement hérité de takeBreak()
    • Une classe RobotWorker qui implémente (implements) Worker. Ajoutez une propriété String model. Comme les robots ne sont pas vraiment des travailleurs mais peuvent faire ce que les travailleurs font, fournissez des implémentations complètement personnalisées : work() doit afficher Robot [model] is assembling parts et takeBreak() doit afficher Robot [model] is recharging
  • main.dart : Importez votre fichier de travailleur et démontrez les deux approches :
    • Créez un OfficeWorker nommé 'Alice' dans le département 'Marketing'
    • Créez un RobotWorker avec le modèle 'RX-7'
    • Pour l'employé de bureau, appelez work() puis takeBreak()
    • Affichez une ligne vide
    • Pour le robot travailleur, appelez work() puis takeBreak()

Remarquez comment OfficeWorker hérite automatiquement de takeBreak() parce qu'il étend Worker - il "est" véritablement un travailleur. En revanche, RobotWorker doit fournir sa propre implémentation pour tout car il n'implémente que l'interface - il "peut faire" ce qu'un travailleur fait, mais à sa propre manière robotique.

Sortie attendue :

Alice is typing reports in Marketing
Alice takes a coffee break

Robot RX-7 is assembling parts
Robot RX-7 is recharging

Aide-mémoire

Utilisez extends pour hériter du comportement d'une classe parente. La sous-classe reçoit automatiquement toutes les méthodes parentes et peut les surcharger :

class Animal {
  void breathe() {
    print('Breathing...');
  }
}

class Dog extends Animal {
  void bark() {
    print('Woof!');
  }
}

void main() {
  var dog = Dog();
  dog.breathe();  // Inherited automatically
  dog.bark();
}

Utilisez implements pour garantir une structure sans hériter du code. Vous devez fournir votre propre implémentation pour chaque méthode :

class Robot implements Animal {
  @override
  void breathe() {
    print('Ventilating circuits...');
  }
}

Différences clés :

  • extends : « Je suis un type de ceci » - véritable héritage avec partage de code
  • implements : « Je peux faire ce que ceci fait » - impose un contrat avec une logique personnalisée
  • Vous ne pouvez étendre qu'une seule classe, mais vous pouvez implémenter plusieurs interfaces

Choisissez extends pour les véritables relations parent-enfant où le comportement doit être hérité. Choisissez implements lorsque vous avez besoin de flexibilité ou que vous souhaitez imposer un contrat sans partager l'implémentation.

Essayez vous-même

import 'worker.dart';

void main() {
  // TODO: Créer un OfficeWorker nommé 'Alice' dans le département 'Marketing'
  
  // TODO: Créer un RobotWorker avec le modèle 'RX-7'
  
  // TODO: Pour l'employé de bureau, appeler work() puis takeBreak()
  
  // TODO: Afficher une ligne vide
  
  // TODO: Pour le robot, appeler work() puis takeBreak()
}
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