Versiegelte Klassen (Dart 3)
Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy. Lektion 85 von 110.
Dart 3 führte versiegelte Klassen ein, die einschränken, welche Klassen sie erweitern oder implementieren können. Wenn du eine Klasse als sealed kennzeichnest, können nur Klassen in derselben Datei ihre direkten Untertypen sein. Dadurch entsteht eine geschlossene Menge bekannter Untertypen.
sealed class Result {}
class Success extends Result {
final String data;
Success(this.data);
}
class Failure extends Result {
final String error;
Failure(this.error);
}Die Stärke versiegelter Klassen ergibt sich aus der Vollständigkeitsprüfung. Wenn du über einen versiegelten Typ wechselst, kennt der Compiler alle möglichen Untertypen und stellt sicher, dass du jeden einzelnen behandelst:
String handleResult(Result result) {
return switch (result) {
Success(data: var d) => 'Got: $d',
Failure(error: var e) => 'Error: $e',
};
// Kein Default erforderlich – der Compiler weiß, dass alle Fälle abgedeckt sind!
}
void main() {
var success = Success('Hello');
var failure = Failure('Not found');
print(handleResult(success)); // Got: Hello
print(handleResult(failure)); // Error: Not found
}Wenn Sie einer sealed class einen neuen Subtyp hinzufügen, wird der Compiler jede switch-Anweisung markieren, die diesen nicht berücksichtigt. Dies macht sealed classes ideal für die Modellierung von Zuständen, Ergebnissen oder anderen Szenarien, in denen eine feste Anzahl von Varianten vorliegt. Im Gegensatz zu abstract classes garantieren sealed classes, dass kein externer Code unerwartete Subtypen hinzufügen kann.
Aufgabe
EinfachErstellen wir einen Handler für Netzwerkanfragen mithilfe von versiegelten Klassen! Du erstellst ein typsicheres System, das verschiedene Zustände einer Netzwerkantwort modelliert und sicherstellt, dass jedes mögliche Ergebnis ordnungsgemäß behandelt wird.
Du organisierst deinen Code in zwei Dateien:
response.dart: Erstelle eine Hierarchie versiegelter Klassen, die alle möglichen Zustände einer Netzwerkantwort darstellt:- Eine versiegelte Klasse namens
NetworkResponse, die als Basisklasse für alle Antworttypen dient - Eine Klasse
Loading, dieNetworkResponseerweitert und über ein FeldString messageverfügt (z. B. „Fetching data...“) - Eine Klasse
Success, dieNetworkResponseerweitert und über ein FeldString datasowie ein Feldint statusCodeverfügt - Eine Klasse
Error, dieNetworkResponseerweitert und über ein FeldString errorMessagesowie ein Feldint errorCodeverfügt
- Eine versiegelte Klasse namens
main.dart: Importiere deine Antwortdatei und erstelle eine Funktion, die mithilfe eines switch-Ausdrucks alle Antworttypen verarbeitet:- Erstelle eine Funktion
handleResponse(NetworkResponse response), die einenStringzurückgibt - Verwende einen switch-Ausdruck mit Pattern Matching, um jeden Fall zu behandeln:
- Für
Loading: GibStatus: [message]zurück - Für
Success: GibSuccess ([statusCode]): [data]zurück - Für
Error: GibError ([errorCode]): [errorMessage]zurück
- Für
- Erstelle drei Antwortinstanzen und gib das Ergebnis der Verarbeitung jeder Instanz aus:
- Ein
Loadingmit der NachrichtPlease wait... - Ein
Successmit den DatenUser profile loadedund dem Statuscode200 - Ein
Errormit der FehlermeldungNot foundund dem Fehlercode404
- Ein
- Erstelle eine Funktion
Das Schöne an versiegelten Klassen ist, dass der Compiler sicherstellt, dass du jeden möglichen Antworttyp behandelst – ein Standardfall ist nicht erforderlich!
Erwartete Ausgabe:
Status: Please wait...
Success (200): User profile loaded
Error (404): Not foundProbier es selbst
import 'response.dart';
// TODO: Erstelle eine Funktion handleResponse(NetworkResponse response)
// die einen String zurückgibt
// Verwende einen switch-Ausdruck mit Pattern Matching, um jeden Fall zu behandeln:
// - Für Loading: gib "Status: [message]" zurück
// - Für Success: gib "Success ([statusCode]): [data]" zurück
// - Für Error: gib "Error ([errorCode]): [errorMessage]" zurück
void main() {
// TODO: Erstelle eine Loading-Instanz mit der Nachricht "Please wait..."
// TODO: Erstelle eine Success-Instanz mit den Daten "User profile loaded" und dem Statuscode 200
// TODO: Erstelle eine Error-Instanz mit der Fehlermeldung "Not found" und dem Fehlercode 404
// TODO: Gib das Ergebnis der Verarbeitung jeder Antwort 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 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