Einführung in Mixins
Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy. Lektion 50 von 110.
Sie haben gelernt, dass Dart nur das Erweitern einer Klasse erlaubt, und obwohl Sie mehrere Schnittstellen implementieren können, müssen Sie den gesamten Code selbst schreiben. Aber was ist, wenn Sie tatsächlichen Implementierungscode über mehrere nicht verwandte Klassen hinweg teilen möchten? Hier kommen Mixins ins Spiel.
Ein Mixin ist eine Möglichkeit, Code in mehreren Klassenhierarchien wiederzuverwenden. Stell es dir als eine Sammlung von Methoden und Eigenschaften vor, die du in jede Klasse „einmischen“ kannst und ihr dadurch neue Fähigkeiten verleihst, ohne Vererbung zu verwenden.
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(); // Aus dem Mixin
var fish = Fish();
fish.swim(); // Gleiche Implementierung, andere Klasse
}Beachte das Schlüsselwort with – so wendest du ein Mixin auf eine Klasse an. Anders als bei implements musst du die Methode nicht selbst schreiben. Das Mixin stellt den eigentlichen Code bereit, und deine Klasse erhält diese Funktionalität automatisch.
Mixins lösen ein echtes Problem: Duck und Fish sind nicht durch Vererbung miteinander verwandt, dennoch benötigen beide ein Schwimmverhalten. Mit Mixins schreiben Sie den Code einmal und teilen ihn überall dort, wo er benötigt wird.
Aufgabe
EinfachLass uns ein Musikinstrument-System erstellen, das zeigt, wie Mixins dir ermöglichen, Verhalten über voneinander unabhängige Klassen hinweg zu teilen. Du erstellst ein Mixin, das Tuning-Funktionalität bereitstellt, und wendest es anschließend auf verschiedene Instrumente an, die nicht durch Vererbung miteinander verbunden sind.
Du wirst deinen Code auf zwei Dateien aufteilen:
instruments.dart: Definiere hier dein Mixin und deine Instrumentklassen:- Ein
Tunable-Mixin mit einer Methodetune(), dieTuning the instrument...ausgibt, und einer MethodecheckTuning(), dieTuning is perfect!ausgibt - Eine
Guitar-Klasse, die dasTunable-Mixin verwendet. Füge eineString brand-Eigenschaft mit einem Konstruktor hinzu. Füge eine Methodestrum()hinzu, die[brand] guitar strumming chordsausgibt - Eine
Piano-Klasse, die ebenfalls dasTunable-Mixin verwendet. Füge eineint keys-Eigenschaft mit einem Konstruktor hinzu. Füge eine Methodeplay()hinzu, diePlaying [keys]-key pianoausgibt
- Ein
main.dart: Importiere deine Instrumentdatei und zeige, wie beide voneinander unabhängigen Instrumente durch dasselbe Mixin Tuning-Fähigkeiten erhalten:- Erstelle eine
Guitarmit der Marke'Fender' - Erstelle ein
Pianomit88Tasten - Für die Gitarre: Rufe
tune(), dannstrum()und anschließendcheckTuning()auf - Gib eine leere Zeile aus
- Für das Klavier: Rufe
tune(), dannplay()und anschließendcheckTuning()auf
- Erstelle eine
Beachte, dass Guitar und Piano völlig unterschiedliche Instrumente ohne Vererbungsbeziehung sind, aber beide durch das Tunable-Mixin genau dieselben Tuning-Methoden erhalten. Du schreibst den Tuning-Code nur einmal, und beide Klassen können ihn mit dem Schlüsselwort with verwenden.
Erwartete Ausgabe:
Tuning the instrument...
Fender guitar strumming chords
Tuning is perfect!
Tuning the instrument...
Playing 88-key piano
Tuning is perfect!Probier es selbst
import 'instruments.dart';
void main() {
// TODO: Erstelle eine Gitarre mit der Marke 'Fender'
// TODO: Erstelle ein Klavier mit 88 Tasten
// TODO: Für die Gitarre: rufe tune() auf, dann strum(), dann checkTuning()
// TODO: Drucke eine Leerzeile
// TODO: Für das Klavier: rufe tune() auf, dann play(), dann checkTuning()
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienBibliotheken & ImportsEinführung in die OOPKlassen vs. ObjekteDas Schlüsselwort thisMethodenInstanzvariablenGrundlagen von KonstruktorenRückblick – Einfacher Taschenrechner4Null-Sicherheit
Einführung in die Null-SicherheitNullable vs. Non-NullableDie Operatoren ? und !Late-Schlüsselwort und Null-SicherheitNull-bewusste OperatorenNull-Sicherheit in KlassenRückblick – Benutzers профilsystem7Abstrakte Klassen & Interfaces
Abstrakte KlassenAbstrakte MethodenInterfaces in DartImplizite InterfacesImplementieren vs. ErweiternMehrere InterfacesZusammenfassung – Formrechner10Collections & Generics
Übersicht über List, Set und MapTypsichere CollectionsGenerische KlassenGenerische MethodenGenerische EinschränkungenIterable & IteratorRückblick – Generischer Speicher13Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungErweiterungsmethodenAufrufbare KlassenVersiegelte Klassen (Dart 3)Records (Dart 3)Muster & Matching (3.0)Enums mit Methoden16Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen2Konstruktoren in Dart
StandardkonstruktorBenannte KonstruktorenInitialisierungslistenKonstantenkonstruktorenFactory-KonstruktorenWeiterleitende KonstruktorenRückblick – Shape Builder5Kapselung
Öffentliche vs. private MemberDie _-Präfix-KonventionBibliotheksweite SichtbarkeitTiefergehende Getter & SetterInformationsverbergungRückblick – Studierendendaten8Mixins
Einführung in MixinsMixins erstellenMehrere Mixins verwendenDas Schlüsselwort „on“ in MixinsMixin vs. VererbungMixin vs. SchnittstelleRückblick – Tiersystem11Spezielle Methoden
toString()-ÜberschreibunghashCode- & ==-ÜberschreibungComparable-Schnittstellecall()-MethodenoSuchMethod-ÜberschreibungWiederholung – Benutzerdefinierte Collection14Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFabrikmusterBeobachtermusterStrategiemuster17Abschließende Herausforderungen
E-Learning-PlattformBankingsystemSpielcharaktersystemFahrzeugvermietung3Klassen-Eigenschaften
Instanz- vs. statische MemberFinal- und Const-FelderLate-VariablenStatische Methoden und FelderGetter und SetterRückblick – Bankkontoverwaltung6Vererbung
Grundlegende VererbungDas Schlüsselwort superMethodenüberschreibungDie Annotation @overrideDas Schlüsselwort final für KlassenKonstruktoren und VererbungZusammenfassung – Mitarbeiterhierarchie9Polymorphismus
Grundlagen des PolymorphismusPolymorphismus über InterfacesLaufzeit-TypüberprüfungDie Operatoren is & asCovariant-SchlüsselwortZusammenfassung – ZahlungsprozessorÜbe selbstständig: Online-Dart-Compiler