Late-Variablen
Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy — Lektion 19 von 110.
Das Schlüsselwort late teilt Dart mit, dass eine nicht-nullbare Variable initialisiert wird, bevor sie verwendet wird, auch wenn sie nicht sofort zugewiesen wird. Dies ist nützlich, wenn Sie ein Feld nicht in der Deklaration oder im Konstruktor initialisieren können, Sie aber sicher sind, dass es einen Wert haben wird, bevor darauf zugegriffen wird.
class User {
late String username;
void initialize(String name) {
username = name;
}
void greet() {
print('Hello, $username!');
}
}
User user = User();
user.initialize('Alice');
user.greet(); // Hallo, Alice!Ohne late würde Dart bemängeln, dass username nicht initialisiert ist. Der late-Modifikator verspricht, dass Sie einen Wert zuweisen, bevor Sie ihn lesen.
Ein weiterer Vorteil von late ist die verzögerte Initialisierung (lazy initialization). Eine late-Variable mit einem Initialisierer berechnet ihren Wert erst beim ersten Zugriff:
class Config {
late String settings = loadSettings();
String loadSettings() {
print('Loading...');
return 'default';
}
}
Config config = Config();
print('Config created');
print(config.settings); // "Loading..." wird hier ausgegeben, dann "default"Die loadSettings()-Methode wird erst ausgeführt, wenn auf settings zum ersten Mal zugegriffen wird, nicht wenn das Objekt erstellt wird. Seien Sie jedoch vorsichtig – der Zugriff auf eine late-Variable, bevor sie initialisiert wurde, löst einen Laufzeitfehler aus.
Aufgabe
EinfachLassen Sie uns einen Datenbankverbindungsmanager erstellen, der sowohl die verzögerte Initialisierung als auch die Lazy-Initialisierung unter Verwendung von late-Variablen demonstriert.
Sie werden zwei Dateien erstellen, um Ihren Code zu organisieren:
database.dart: Definieren Sie eineDatabase-Klasse, die eine Datenbankverbindung simuliert. Ihre Klasse sollte Folgendes enthalten:- Ein
late String connectionString, das nach der Erstellung des Objekts gesetzt wird. - Ein
late String statusmit einem Lazy-Initializer, derChecking connection...ausgibt und'Connected'zurückgibt. - Eine
connect(String connStr)-Methode, die denconnectionStringsetzt undConnection configured: [connectionString]ausgibt. - Eine
query(String sql)-Methode, dieExecuting on [connectionString]: [sql]ausgibt. - Eine
checkStatus()-Methode, dieStatus: [status]ausgibt (dies wird beim ersten Aufruf die Lazy-Initialisierung auslösen).
- Ein
main.dart: Importieren Sie Ihre Datenbankklasse und demonstrieren Sie beide Verwendungen vonlate:- Erstellen Sie eine
Database-Instanz. - Geben Sie
Database object createdaus. - Rufen Sie
connect()mit dem Connection-String'localhost:5432/mydb'auf. - Rufen Sie
query()mit'SELECT * FROM users'auf. - Rufen Sie
checkStatus()auf, um die Lazy-Initialisierung auszulösen.
- Erstellen Sie eine
Beachten Sie, wie connectionString nach der Objekterstellung manuell gesetzt wird, während status seinen Wert erst beim ersten Zugriff berechnet.
Erwartete Ausgabe:
Database object created
Connection configured: localhost:5432/mydb
Executing on localhost:5432/mydb: SELECT * FROM users
Checking connection...
Status: ConnectedSpickzettel
Das Schlüsselwort late ermöglicht es Ihnen, nicht-nullable Variablen zu deklarieren, die später initialisiert werden, bevor sie verwendet werden:
class User {
late String username;
void initialize(String name) {
username = name;
}
}
User user = User();
user.initialize('Alice');Lazy Initialization: Eine late-Variable mit einem Initialisierer berechnet ihren Wert erst beim ersten Zugriff:
class Config {
late String settings = loadSettings();
String loadSettings() {
print('Loading...');
return 'default';
}
}
Config config = Config(); // loadSettings() wurde noch nicht aufgerufen
print(config.settings); // loadSettings() wird hier aufgerufenWarnung: Der Zugriff auf eine late-Variable vor der Initialisierung löst einen Laufzeitfehler aus.
Probier es selbst
import 'database.dart';
void main() {
// TODO: Erstelle eine Database-Instanz
// TODO: Gib 'Database object created' aus
// TODO: Rufe connect() mit 'localhost:5432/mydb' auf
// TODO: Rufe query() mit 'SELECT * FROM users' auf
// TODO: Rufe checkStatus() auf, um die verzögerte Initialisierung auszulösen
}
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