Mixin vs. Vererbung
Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy. Lektion 54 von 110.
Nachdem Sie nun gelernt haben, wie Mixins funktionieren, lassen Sie uns klären, wann man sie anstelle von Vererbung einsetzt. Der entscheidende Unterschied liegt in der Beziehung, die sie ausdrücken.
Vererbung stellt eine „is-a“-Beziehung dar. Ein Dog ist ein Animal. Die Unterklasse ist eine spezialisierte Version der Elternklasse, und man kann nur eine Klasse erweitern.
Mixins hingegen stellen eine „Kann-Beziehung“ dar. Ein Dog kann schwimmen, aber Schwimmen ist nicht das, was einen Hund definiert.
// Vererbung: Dog IST ein Animal
class Animal {
String name;
Animal(this.name);
}
class Dog extends Animal {
Dog(String name) : super(name);
}
// Mixin: Dog KANN schwimmen (wird aber nicht durch Schwimmen definiert)
mixin Swimming {
void swim() => print('Swimming');
}
class Dog extends Animal with Swimming {
Dog(String name) : super(name);
}Verwenden Sie Vererbung, wenn Klassen eine grundlegende Identität teilen und Sie Konstruktoren in der Elternklasse benötigen. Verwenden Sie Mixins, wenn Sie Klassen Funktionen hinzufügen möchten, die keinen gemeinsamen Vorfahren haben.
| Merkmal | Vererbung | Mixin |
|---|---|---|
| Beziehung | ist-ein | kann |
| Beschränkung | Nur ein Elternteil | Mehrere Mixins |
| Konstruktoren | Erlaubt | Nicht erlaubt |
| Anwendungsfall | Spezialisierung | Gemeinsames Verhalten |
Das Beste daran? Sie können beides kombinieren – eine Klasse erweitern und mehrere Funktionen einmischen, wodurch Ihre Klassen genau die Features erhalten, die sie benötigen.
Aufgabe
EinfachErstelle ein Arbeitersystem, das zeigt, wann Vererbung und wann Mixins verwendet werden sollten. Du erstellst eine Basisklasse für die „ist-eine“-Beziehung und Mixins für „kann“-Fähigkeiten und kombinierst sie anschließend, um zu zeigen, wie beide Ansätze zusammen funktionieren.
Du organisierst deinen Code in drei Dateien:
worker.dart: Definiere deine Basisklasse, die die grundlegende Identität aller Arbeiter festlegt:- Eine
Worker-Klasse mit den EigenschaftenString nameundString department. Füge einen Konstruktor hinzu, der beide Werte entgegennimmt. Füge eine Methodeintroduce()hinzu, die[name] works in [department]ausgibt.
- Eine
skills.dart: Definiere Mixins, die Fähigkeiten darstellen, über die Arbeiter verfügen können (die „kann“-Beziehungen):- Ein
CanCode-Mixin mit einer MethodewriteCode(), dieWriting code...ausgibt. - Ein
CanDesign-Mixin mit einer MethodecreateDesign(), dieCreating design...ausgibt. - Ein
CanManage-Mixin mit einer MethodeleadTeam(), dieLeading the team...ausgibt.
- Ein
main.dart: Importiere beide Dateien und erstelle spezialisierte Arbeitertypen, die Vererbung mit Mixins kombinieren:- Eine
Developer-Klasse, dieWorkererweitert und dasCanCode-Mixin verwendet. - Eine
TechLead-Klasse, dieWorkererweitert und sowohl dasCanCode- als auch dasCanManage-Mixin verwendet. - Erstelle einen
Developernamens'Alice'in der Abteilung'Engineering'. - Erstelle einen
TechLeadnamens'Bob'in der Abteilung'Engineering'. - Für Alice: Rufe zuerst
introduce()und dannwriteCode()auf. - Gib eine leere Zeile aus.
- Für Bob: Rufe
introduce(), dannwriteCode()und anschließendleadTeam()auf.
- Eine
Beachte, dass sowohl Developer als auch TechLead Arbeiter sind (Vererbung), aber unterschiedliche Dinge tun können (Mixins). TechLead kombiniert mehrere Fähigkeiten, ohne Mehrfachvererbung zu benötigen.
Erwartete Ausgabe:
Alice works in Engineering
Writing code...
Bob works in Engineering
Writing code...
Leading the team...Probier es selbst
import 'worker.dart';
import 'skills.dart';
// TODO: Erstelle eine Developer-Klasse, die Worker erweitert und das CanCode-Mixin verwendet
// TODO: Erstelle eine TechLead-Klasse, die Worker erweitert und sowohl CanCode- als auch CanManage-Mixins verwendet
void main() {
// TODO: Erstelle einen Developer namens 'Alice' in der Abteilung 'Engineering'
// TODO: Rufe introduce() und dann writeCode() für Alice auf
// TODO: Gib eine Leerzeile aus
// TODO: Erstelle einen TechLead namens 'Bob' in der Abteilung 'Engineering'
// TODO: Rufe introduce(), writeCode() und dann leadTeam() für Bob auf
}
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