Asynchrone Konstruktoren
Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy. Lektion 79 von 110.
Konstruktoren in Dart können nicht als async markiert werden – sie müssen sofort eine Instanz der Klasse zurückgeben, kein Future. Wie erstellt man also Objekte, die eine asynchrone Initialisierung erfordern, wie das Laden von Daten aus einer Datenbank oder das Abrufen von Konfigurationen?
Die Lösung besteht darin, eine statische asynchrone Factory-Methode zu verwenden. Halte den Konstruktor privat (oder einfach) und stelle eine statische Methode bereit, die die asynchrone Arbeit ausführt und ein Future deiner Klasse zurückgibt:
class UserProfile {
final String name;
final int age;
UserProfile._(this.name, this.age); // Privater Konstruktor
static Future<UserProfile> create(String userId) async {
// Simuliere das Abrufen von Daten
await Future.delayed(Duration(seconds: 1));
return UserProfile._('Alice', 25);
}
}
Future<void> main() async {
var user = await UserProfile.create('123');
print(user.name); // Alice
}Der private Konstruktor UserProfile._ übernimmt die eigentliche Objekterstellung, während die statische Methode create() die gesamte asynchrone Arbeit übernimmt. Aufrufer verwenden await, um das vollständig initialisierte Objekt zu erhalten.
Dieses Muster stellt sicher, dass Ihr Objekt vollständig einsatzbereit ist, sobald Sie es erhalten – keine teilweise initialisierten Zustände oder fehlenden Daten. Es wird häufig für Klassen verwendet, die Ressourcen laden, Verbindungen zu Diensten herstellen oder eine Einrichtung durchführen müssen, die Zeit in Anspruch nimmt.
Aufgabe
EinfachErstellen wir einen Konfigurationslader, der zeigt, wie man die asynchrone Initialisierung in Klassen handhabt! Da Konstruktoren nicht asynchron sein können, verwendest du das Muster der statischen Factory-Methode, um Objekte zu erstellen, deren Daten zunächst „geladen“ werden müssen.
Du organisierst deinen Code in zwei Dateien:
config_loader.dart: Erstelle eineConfigLoader-Klasse, die das asynchrone Laden von Konfigurationseinstellungen simuliert. Deine Klasse sollte Folgendes enthalten:- Drei finale Felder:
appName(String),version(String) undmaxUsers(int) - Einen privaten Konstruktor, der alle drei Felder initialisiert
- Eine statische asynchrone Factory-Methode namens
load, die einenString configId-Parameter entgegennimmt und einFuture<ConfigLoader>zurückgibt. Diese Methode sollte:Future.delayed()mit 100 Millisekunden verwenden, um die Ladezeit zu simulieren- Die Konfigurationswerte basierend auf
configIderzeugen:appName: die configId mit angehängtem" App"version:"1.0.", gefolgt von der Länge von configIdmaxUsers: die Länge von configId multipliziert mit 10
- Eine neue
ConfigLoader-Instanz mit diesen Werten zurückgeben
- Eine
displayInfo()-Methode, die die Konfiguration in diesem Format ausgibt:Config: [appName] v[version] (max [maxUsers] users)
- Drei finale Felder:
main.dart: Importiere deinen Konfigurationslader und demonstriere das Muster der asynchronen Initialisierung:Loading configurations...ausgeben- Eine Konfiguration mit der configId
"Production"laden und ihredisplayInfo()-Methode aufrufen - Eine Konfiguration mit der configId
"Dev"laden und ihredisplayInfo()-Methode aufrufen All configs loaded!ausgeben
Beachte, wie die statische load-Methode die gesamte asynchrone Arbeit übernimmt, während der private Konstruktor einfach die Werte zuweist. Aufrufer verwenden await, um ein vollständig initialisiertes Objekt zu erhalten!
Erwartete Ausgabe:
Loading configurations...
Config: Production App v1.0.10 (max 100 users)
Config: Dev App v1.0.3 (max 30 users)
All configs loaded!Probier es selbst
import 'config_loader.dart';
void main() async {
// TODO: Gebe "Loading configurations..." aus
// TODO: Lade eine Konfiguration mit configId "Production"
// und rufe deren displayInfo() Methode auf
// TODO: Lade eine Konfiguration mit configId "Dev"
// und rufe deren displayInfo() Methode auf
// TODO: Gebe "All configs loaded!" 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 – Zahlungsprozessor12Asynchrone OOP
Futures & async/awaitStream-GrundlagenStream-ControllerAsynchrone KonstruktorenAsync in KlassenmethodenZusammenfassung – DatenabrufÜbe selbstständig: Online-Dart-Compiler