Menu
Coddy logo textTech

Mixin ou interface

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

Vous avez vu comment les mixins se comparent à l'héritage. Comparons maintenant les mixins aux interfaces, car les deux vous permettent de travailler avec plusieurs types. La différence clé réside dans ce qu'elles fournissent : les interfaces définissent un contrat, tandis que les mixins fournissent une implémentation.

Lorsque vous implémentez une interface, vous vous engagez à fournir certaines méthodes, mais vous écrivez vous-même tout le code. Lorsque vous utilisez un mixin, vous obtenez gratuitement le code réel.

// Approche par interface - vous devez tout implémenter
abstract class Printable {
  void printInfo();
}

class Report implements Printable {
  @override
  void printInfo() {
    print('Printing report...');  // Vous écrivez ceci
  }
}

// Approche par mixin - implémentation incluse
mixin Printable {
  void printInfo() {
    print('Printing...');  // Déjà écrit pour vous
  }
}

class Report with Printable {}  // Obtient printInfo() automatiquement

Alors, quand faut-il utiliser chacun d’eux ? Utilisez une interface lorsque différentes classes ont besoin des mêmes signatures de méthodes, mais de différentes implémentations. Utilisez un mixin lorsque les classes doivent partager exactement le même comportement.

FonctionnalitéInterfaceMixin
FournitContrat uniquementContrat + code
ImplémentationVous l’écrivezIncluse
Mot-cléimplementswith
Idéal pourDes comportements différents, une même APIComportement partagé

Vous pouvez même combiner les deux approches : utiliser des interfaces pour définir ce qu'une classe peut faire, et des mixins pour fournir des implémentations communes le cas échéant. En Dart, lors de la combinaison des deux, placez toujours with avant implements :

class MyClass with SomeMixin implements SomeInterface {
  // with se place avant implements
}
challenge icon

Défi

Facile

Construisons un système de notifications qui montre quand utiliser des interfaces plutôt que des mixins. Vous allez créer une interface pour les notifications qui nécessitent différentes implémentations, ainsi qu’un mixin pour le comportement partagé de journalisation qui doit être identique pour tous les types de notifications.

Vous organiserez votre code en trois fichiers :

  • notifiable.dart : définissez une classe abstraite Notifiable qui agit comme une interface. Elle doit déclarer deux méthodes abstraites : send(String message) et getChannel(), qui renvoie un String. Les différents types de notifications implémenteront ces méthodes différemment selon leur canal spécifique.
  • logging.dart : créez un mixin Logging qui fournit le comportement partagé que toutes les notifications doivent avoir. Incluez une méthode logSent(String channel, String message) qui affiche [LOG] Sent via [channel]: [message] et une méthode logTimestamp() qui affiche [LOG] Timestamp recorded. Ce comportement est identique pour tous les types de notifications, ce qui en fait un cas idéal pour un mixin.
  • main.dart : importez les deux fichiers et créez deux classes de notifications qui combinent l’interface avec le mixin :
    • Une classe EmailNotification qui utilise le mixin Logging et implémente Notifiable. Sa méthode getChannel() doit renvoyer 'Email', et sa méthode send() doit afficher Sending email: [message], puis appeler logSent() avec le canal et le message, puis appeler logTimestamp()
    • Une classe SMSNotification qui utilise le mixin Logging et implémente Notifiable. Sa méthode getChannel() doit renvoyer 'SMS', et sa méthode send() doit afficher Sending SMS: [message], puis appeler logSent() avec le canal et le message, puis appeler logTimestamp()
    Créez ensuite un EmailNotification et appelez send('Hello World'), affichez une ligne vide, créez un SMSNotification et appelez send('Quick update')

Remarquez comment l’interface force chaque classe à écrire ses propres implémentations de send() et getChannel() (comportement différent), tandis que le mixin fournit les méthodes de journalisation qui fonctionnent de manière identique pour les deux classes (comportement partagé).

Sortie attendue :

Sending email: Hello World
[LOG] Sent via Email: Hello World
[LOG] Timestamp recorded

Sending SMS: Quick update
[LOG] Sent via SMS: Quick update
[LOG] Timestamp recorded

Essayez vous-même

import 'notifiable.dart';
import 'logging.dart';

// TODO: Créer la classe EmailNotification qui :
//       - utilise le mixin Logging (avec with)
//       - implémente Notifiable (avec implements)
//       - getChannel() retourne 'Email'
//       - send() affiche 'Sending email: [message]', puis appelle logSent(), puis logTimestamp()

// TODO: Créer la classe SMSNotification qui :
//       - utilise le mixin Logging (avec with)
//       - implémente Notifiable (avec implements)
//       - getChannel() retourne 'SMS'
//       - send() affiche 'Sending SMS: [message]', puis appelle logSent(), puis logTimestamp()

void main() {
  // TODO: Créer une EmailNotification et appeler send('Hello World')
  
  // TODO: Afficher une ligne vide
  
  // TODO: Créer une SMSNotification et appeler send('Quick update')
}
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