Konstruktoren & Vererbung
Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy — Lektion 41 von 110.
Wenn eine Unterklasse eine Basisklasse erweitert, muss der Konstruktor der Basisklasse aufgerufen werden, um geerbte Felder ordnungsgemäß zu initialisieren. Dart bietet flexible Möglichkeiten, dies über die Initialisierungsliste unter Verwendung von super zu handhaben.
Wenn die Elternklasse einen parametrisierten Konstruktor hat, muss die Kindklasse diesen explizit aufrufen:
class Person {
String name;
int age;
Person(this.name, this.age);
}
class Student extends Person {
String school;
Student(String name, int age, this.school) : super(name, age);
}Dart 2.17 führte Super-Parameter ein, eine sauberere Syntax, die Parameter direkt an den Konstruktor der Elternklasse weiterleitet:
class Student extends Person {
String school;
// super.name und super.age werden direkt an den Konstruktor von Person weitergeleitet
Student(super.name, super.age, this.school);
}Wenn Sie mit benannten Konstruktoren arbeiten, geben Sie an, welcher Konstruktor der Elternklasse aufgerufen werden soll:
class Employee extends Person {
String department;
Employee(super.name, super.age, this.department);
Employee.intern(String name, this.department) : super(name, 18);
}Die Grundregel ist einfach: Die Elternklasse muss vollständig initialisiert sein, bevor die Kindklasse ihre eigenen Eigenschaften hinzufügt. Ob Sie den traditionellen super()-Aufruf oder die neueren Super-Parameter verwenden, Dart stellt sicher, dass die Vererbungskette ordnungsgemäß von der Eltern- zur Kindklasse aufgebaut wird.
Aufgabe
EinfachLassen Sie uns ein Produktinventarsystem erstellen, das zeigt, wie Konstruktoren mit Vererbung funktionieren. Sie werden eine Hierarchie erstellen, in der verschiedene Produkttypen eine Basis-Produktklasse erweitern, wobei jeder Typ eine ordnungsgemäße Initialisierung durch Eltern-Konstruktoren erfordert.
Sie werden Ihren Code in zwei Dateien organisieren:
product.dart: Definieren Sie hier Ihre Produkthierarchie:- Eine
Product-Klasse mit den EigenschaftenString nameunddouble price, einem Konstruktor, der beide Werte entgegennimmt, und einer Methodeinfo(), die[name]: $[price]ausgibt - Eine
Book-Klasse, dieProducterweitert und eineString author-Eigenschaft hinzufügt. Verwenden Sie Super-Parameter, umnameundpricean den Eltern-Konstruktor weiterzuleiten - Eine
Electronics-Klasse, dieProducterweitert und eineint warranty-Eigenschaft (in Monaten) hinzufügt. Verwenden Sie den traditionellensuper()-Aufruf in der Initialisierungsliste, um Werte an das Elternteil zu übergeben
- Eine
main.dart: Importieren Sie Ihre Produktdatei und demonstrieren Sie beide Ansätze der Konstruktor-Vererbung:- Erstellen Sie ein
Bookmit dem Namen'Dart Essentials', dem Preis29.99und dem Autor'Jane Smith' - Rufen Sie dessen
info()-Methode auf und geben Sie dannAuthor: [author]aus - Geben Sie eine Leerzeile aus
- Erstellen Sie ein
Electronics-Objekt mit dem Namen'Wireless Mouse', dem Preis45.50und der Garantie24 - Rufen Sie dessen
info()-Methode auf und geben Sie dannWarranty: [warranty] monthsaus
- Erstellen Sie ein
Beide Kindklassen erben die info()-Methode von Product, ohne sie überschreiben zu müssen. Der Hauptunterschied liegt darin, wie sie den Eltern-Konstruktor aufrufen – Book verwendet die sauberere Super-Parameter-Syntax, während Electronics den traditionellen Ansatz mit super() in der Initialisierungsliste nutzt.
Erwartete Ausgabe:
Dart Essentials: $29.99
Author: Jane Smith
Wireless Mouse: $45.5
Warranty: 24 monthsSpickzettel
Wenn eine Kindklasse eine Elternklasse erweitert, muss der Konstruktor der Elternklasse aufgerufen werden, um die geerbten Felder ordnungsgemäß zu initialisieren.
Traditioneller Ansatz – expliziter Aufruf des Elternkonstruktors in der Initialisierungsliste:
class Person {
String name;
int age;
Person(this.name, this.age);
}
class Student extends Person {
String school;
Student(String name, int age, this.school) : super(name, age);
}Super-Parameter (Dart 2.17+) – Parameter direkt an den Elternkonstruktor weiterleiten:
class Student extends Person {
String school;
Student(super.name, super.age, this.school);
}Benannte Konstruktoren – angeben, welcher Elternkonstruktor aufgerufen werden soll:
class Employee extends Person {
String department;
Employee(super.name, super.age, this.department);
Employee.intern(String name, this.department) : super(name, 18);
}Probier es selbst
import 'product.dart';
void main() {
// TODO: Erstelle ein Book mit:
// - name: 'Dart Essentials'
// - price: 29.99
// - author: 'Jane Smith'
// TODO: Rufe die Methode info() des Buchs auf
// TODO: Gib "Author: [author]" aus
// TODO: Gib eine Leerzeile aus
// TODO: Erstelle ein Electronics mit:
// - name: 'Wireless Mouse'
// - price: 45.50
// - warranty: 24
// TODO: Rufe die Methode info() der Elektronik auf
// TODO: Gib "Warranty: [warranty] months" aus
}
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 this-SchlüsselwortMethodenInstanzvariablenKonstruktor-GrundlagenWiederholung – Einfacher Taschenrechner4Null-Sicherheit
Einführung in Null-SicherheitNullable vs. Non-NullableDie ? und ! OperatorenLate-Schlüsselwort & Null-SicherheitNull-aware OperatorenNull-Sicherheit in KlassenZusammenfassung – Benutzerprofil-System7Abstrakte Klassen & Interfaces
Abstrakte KlassenAbstrakte MethodenInterfaces in DartImplizite InterfacesImplementieren vs. ErweiternMehrfache InterfacesRückblick – Shape Calculator10Collections & Generics
Überblick über List, Set und MapTypsichere CollectionsGenerische KlassenGenerische MethodenGenerische ConstraintsIterable & IteratorZusammenfassung – Generische Speicherung13Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungExtension MethodsCallable ClassesSealed Classes (Dart 3)Records (Dart 3)Patterns & Matching (3.0)Enums mit Methoden16Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen2Konstruktoren in Dart
Standard-KonstruktorBenannte KonstruktorenInitialisierungslistenKonstante KonstruktorenFactory-KonstruktorenWeiterleitende KonstruktorenZusammenfassung – Shape Builder5Kapselung
Öffentliche vs. private MemberDie _ Präfix-KonventionSichtbarkeit auf Library-EbeneGetter & Setter im DetailInformation HidingRückblick – Schülerdatensätze8Mixins
Einführung in MixinsMixins erstellenMehrere Mixins verwendenDas on-Schlüsselwort in MixinsMixin vs. VererbungMixin vs. InterfaceZusammenfassung - Tiersystem11Spezielle Methoden
toString() überschreibenhashCode & == überschreibenComparable-Interfacecall()-MethodenoSuchMethod überschreibenZusammenfassung – Eigene Collection14Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster3Klasseneigenschaften
Instanz- vs. statische MemberFinal & Const FelderLate-VariablenStatische Methoden & FelderGetter und SetterZusammenfassung – Bankkonto-Manager6Vererbung
Grundlagen der VererbungDas super-SchlüsselwortMethoden überschreibenDie @override-AnnotationDas final-Klassen-SchlüsselwortKonstruktoren & VererbungRückblick – Mitarbeiter-Hierarchie9Polymorphismus
Polymorphismus-GrundlagenPolymorphismus über InterfacesTypprüfung zur LaufzeitDie is & as OperatorenDas covariant SchlüsselwortZusammenfassung – Payment Processor