Introduction aux Mixins
Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy — leçon 50 sur 110.
Vous avez appris que Dart ne permet d'étendre qu'une seule classe, et bien que vous puissiez implémenter plusieurs interfaces, vous devez écrire tout le code vous-même. Mais que se passe-t-il si vous voulez partager du code d'implémentation réel entre plusieurs classes non liées ? C'est là que les mixins entrent en jeu.
Un mixin est un moyen de réutiliser du code dans plusieurs hiérarchies de classes. Considérez-le comme un ensemble de méthodes et de propriétés que vous pouvez « mélanger » à n'importe quelle classe, lui conférant de nouvelles capacités sans utiliser l'héritage.
mixin Swimming {
void swim() {
print('Swimming through the water');
}
}
class Duck with Swimming {
void quack() {
print('Quack!');
}
}
class Fish with Swimming {
void blowBubbles() {
print('Blub blub');
}
}
void main() {
var duck = Duck();
duck.quack();
duck.swim(); // Provient du mixin
var fish = Fish();
fish.swim(); // Même implémentation, classe différente
}Remarquez le mot-clé with - c'est ainsi que vous appliquez un mixin à une classe. Contrairement à implements, vous n'avez pas besoin d'écrire la méthode vous-même. Le mixin fournit le code réel, et votre classe acquiert cette fonctionnalité automatiquement.
Les mixins résolvent un problème réel : Duck et Fish ne sont pas liés par l'héritage, pourtant ils ont tous deux besoin d'un comportement de nage. Avec les mixins, vous écrivez le code une seule fois et vous le partagez partout où c'est nécessaire.
Défi
FacileConstruisons un système d'instruments de musique qui démontre comment les mixins vous permettent de partager un comportement entre des classes non liées. Vous allez créer un mixin qui fournit une fonctionnalité d'accordage, puis l'appliquer à différents instruments qui ne sont pas liés par héritage.
Vous organiserez votre code en deux fichiers :
instruments.dart: Définissez votre mixin et vos classes d'instruments ici :- Un mixin
Tunableavec une méthodetune()qui afficheTuning the instrument...et une méthodecheckTuning()qui afficheTuning is perfect! - Une classe
Guitarqui utilise le mixinTunable. Ajoutez une propriétéString brandavec un constructeur. Incluez une méthodestrum()qui affiche[brand] guitar strumming chords - Une classe
Pianoqui utilise également le mixinTunable. Ajoutez une propriétéint keysavec un constructeur. Incluez une méthodeplay()qui affichePlaying [keys]-key piano
- Un mixin
main.dart: Importez votre fichier d'instruments et démontrez comment les deux instruments non liés acquièrent des capacités d'accordage à partir du même mixin :- Créez une
Guitaravec la marque'Fender' - Créez un
Pianoavec88touches - Pour la guitare : appelez
tune(), puisstrum(), puischeckTuning() - Affichez une ligne vide
- Pour le piano : appelez
tune(), puisplay(), puischeckTuning()
- Créez une
Remarquez comment Guitar et Piano sont des instruments complètement différents sans relation d'héritage, et pourtant ils bénéficient tous deux des mêmes méthodes d'accordage grâce au mixin Tunable. Vous écrivez le code d'accordage une seule fois, et les deux classes peuvent l'utiliser avec le mot-clé with.
Sortie attendue :
Tuning the instrument...
Fender guitar strumming chords
Tuning is perfect!
Tuning the instrument...
Playing 88-key piano
Tuning is perfect!Aide-mémoire
Un mixin est un moyen de réutiliser du code à travers plusieurs classes non liées sans utiliser l'héritage. C'est un ensemble de méthodes et de propriétés que vous pouvez « mélanger » à n'importe quelle classe.
Définissez un mixin en utilisant le mot-clé mixin :
mixin Swimming {
void swim() {
print('Swimming through the water');
}
}Appliquez un mixin à une classe en utilisant le mot-clé with :
class Duck with Swimming {
void quack() {
print('Quack!');
}
}
class Fish with Swimming {
void blowBubbles() {
print('Blub blub');
}
}Contrairement à implements, vous n'avez pas besoin d'écrire l'implémentation de la méthode vous-même - le mixin fournit le code réel, et votre classe acquiert cette fonctionnalité automatiquement.
Duck et Fish peuvent désormais tous deux utiliser la méthode swim() même s'ils ne sont pas liés par l'héritage :
var duck = Duck();
duck.swim(); // Provient du mixin
var fish = Fish();
fish.swim(); // Même implémentation, classe différenteEssayez vous-même
import 'instruments.dart';
void main() {
// TODO: Créer une Guitar avec la marque 'Fender'
// TODO: Créer un Piano avec 88 touches
// TODO: Pour la guitare : appeler tune(), puis strum(), puis checkTuning()
// TODO: Imprimer une ligne vide
// TODO: Pour le piano : appeler tune(), puis play(), puis checkTuning()
}
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
1Les bases de la POO
Fichiers externesBibliothèques et importsIntroduction à la POOClasses vs ObjetsLe mot-clé thisMéthodesVariables d'instanceBases des constructeursRécapitulatif - Calculatrice simple4Null Safety
Introduction à la Null SafetyNullable vs Non-NullableLes opérateurs ? et !Le mot-clé late et la Null SafetyLes opérateurs Null-AwareLa Null Safety dans les classesRécapitulatif - Système de profil utilisateur7Classes abstraites et Interfaces
Classes abstraitesMéthodes abstraitesInterfaces en DartInterfaces implicitesImplémentation vs ExtensionInterfaces multiplesRécapitulatif - Calculateur de formes10Collections et Génériques
Aperçu des List, Set et MapCollections Type-SafeClasses génériquesMéthodes génériquesContraintes de généricitéIterable & IteratorRécapitulatif - Stockage générique2Les constructeurs en Dart
Constructeur par défautConstructeurs nommésListes d'initialisationConstructeurs constantsConstructeurs factoryConstructeurs de redirectionRécapitulatif - Shape Builder5Encapsulation
Membres publics vs privésLa convention du préfixe _Visibilité au niveau de la bibliothèqueApprofondissement des Getters & SettersMasquage d'informationsRécapitulatif - Dossiers d'étudiants8Mixins
Introduction aux MixinsCréation de MixinsUtilisation de plusieurs MixinsLe mot-clé on dans les MixinsMixin vs HéritageMixin vs InterfaceRécapitulatif - Système Animal11Méthodes spéciales
Redéfinition de toString()Redéfinition de hashCode & ==Interface ComparableMéthode call()Redéfinition de noSuchMethodRécapitulatif - Collection personnalisée14Patrons de conception Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron ObservateurPatron Stratégie3Propriétés de classe
Membres d'instance vs statiquesChamps Final & ConstVariables LateMéthodes et champs statiquesGetters et SettersRécapitulatif - Gestionnaire de compte bancaire6Héritage
Bases de l'héritageLe mot-clé superRedéfinition de méthodeL'annotation @overrideLe mot-clé final pour les classesConstructeurs et héritageRécapitulatif - Hiérarchie des employés9Polymorphisme
Bases du polymorphismePolymorphisme via les interfacesVérification de type à l'exécutionLes opérateurs is & asMot-clé covariantRécapitulatif - Processeur de paiement12POO Asynchrone
Futures & async/awaitBases des StreamsStream ControllersConstructeurs asynchronesL'asynchrone dans les méthodes de classeRécapitulatif - Data Fetcher15Patrons de conception Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode ModèlePatron ÉtatPatron CompositePatron Repository