Null-Sicherheit in Klassen
Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy — Lektion 28 von 110.
Beim Entwurf von Klassen müssen Sie entscheiden, welche Felder erforderlich und welche optional sind. Die Null-Sicherheit beeinflusst, wie Sie Instanzvariablen deklarieren und Konstruktoren schreiben.
Nicht-nullbare Felder müssen initialisiert werden, bevor der Konstruktor-Body ausgeführt wird. Dies kann über Initialisierungslisten, Konstruktorparameter oder Standardwerte erfolgen:
class User {
String name; // Muss initialisiert werden
String? bio; // Optional - kann null sein
int age = 0; // Hat einen Standardwert
User(this.name); // name wird über den Parameter initialisiert
}Für Nullable-Felder können Sie diese nicht initialisiert lassen, da sie standardmäßig auf null gesetzt werden. Dies ist nützlich für optionale Daten:
class Product {
String title;
String? description; // Optionale Produktbeschreibung
double? discount; // Standardmäßig kein Rabatt
Product(this.title);
}
var item = Product('Laptop');
print(item.description); // null
print(item.discount); // nullVerwenden Sie beim Zugriff auf Nullable-Felder die Null-aware-Operatoren, die Sie gelernt haben:
class Order {
String id;
User? customer;
Order(this.id);
String getCustomerName() {
return customer?.name ?? 'Guest';
}
}Das Schlüsselwort required in benannten Parametern stellt sicher, dass Aufrufer wesentliche Werte bereitstellen:
class Account {
String email;
String? phone;
Account({required this.email, this.phone});
}
var acc = Account(email: 'test@mail.com'); // phone ist optionalDurch die bewusste Entscheidung zwischen Nullable- und Non-Nullable-Feldern erstellen Sie Klassen, die klar kommunizieren, welche Daten erforderlich und welche optional sind.
Aufgabe
EinfachLassen Sie uns ein Buchungssystem für ein Hotel erstellen, das zeigt, wie man Klassen mit einer durchdachten Mischung aus erforderlichen und optionalen Feldern unter Verwendung von Null-Safety entwirft.
Sie werden Ihren Code in zwei Dateien organisieren:
reservation.dart: Definieren Sie eine KlasseReservation, die eine Hotelbuchung repräsentiert. Jede Reservierung benötigt bestimmte wesentliche Informationen, aber einige Details sind optionale Extras, die Gäste angeben können oder auch nicht. Ihre Klasse sollte Folgendes enthalten:- Ein nicht-nullbares
String guestName- jede Reservierung muss einen Gastnamen haben - Ein nicht-nullbares
int roomNumber- jeder Reservierung muss ein Zimmer zugewiesen werden - Ein nicht-nullbares
int nightsmit einem Standardwert von1- der Mindestaufenthalt beträgt eine Nacht - Ein nullbares
String? specialRequests- Gäste können Sonderwünsche haben - Ein nullbares
DateTime? checkInTime- die genaue Ankunftszeit ist möglicherweise nicht bekannt - Einen Konstruktor, der benannte Parameter mit
requiredfürguestNameundroomNumberverwendet, währendnightsoptional mit seinem Standardwert sein sollte - Eine Methode
getRequestsSummary(), die die Sonderwünsche zurückgibt, falls vorhanden, oder'No special requests'unter Verwendung des??-Operators - Eine Methode
getArrivalInfo(), die die String-Repräsentation der Check-in-Zeit unter Verwendung von?.zurückgibt, odernull, falls nicht gesetzt - Eine Methode
printConfirmation(), die die Reservierungsdetails anzeigt
- Ein nicht-nullbares
main.dart: Importieren Sie Ihre Reservierungsklasse und erstellen Sie Buchungen, die verschiedene Kombinationen von erforderlichen und optionalen Daten zeigen:- Erstellen Sie eine Reservierung für den Gast
'Sarah Johnson'in Zimmer101für3Nächte, mit den Sonderwünschen'Late checkout'und einer Check-in-Zeit, die aufDateTime(2024, 6, 15, 14, 30)gesetzt ist - Erstellen Sie eine Reservierung für den Gast
'Mike Chen'in Zimmer205(verwenden Sie die Standardanzahl an Nächten), wobei nur die Sonderwünsche auf'Extra pillows'gesetzt sind - Erstellen Sie eine Reservierung für den Gast
'Emma Davis'in Zimmer310für2Nächte (lassen Sie beide optionalen Felder auf null) - Rufen Sie für jede Reservierung nacheinander
printConfirmation()auf und geben Sie dannArrival: [result]unter Verwendung vongetArrivalInfo()aus
- Erstellen Sie eine Reservierung für den Gast
Die Methode printConfirmation() sollte in diesem Format drucken:
=== Reservation Confirmed ===
Guest: [guestName]
Room: [roomNumber]
Nights: [nights]
Requests: [getRequestsSummary()]Erwartete Ausgabe:
=== Reservation Confirmed ===
Guest: Sarah Johnson
Room: 101
Nights: 3
Requests: Late checkout
Arrival: 2024-06-15 14:30:00.000
=== Reservation Confirmed ===
Guest: Mike Chen
Room: 205
Nights: 1
Requests: Extra pillows
Arrival: null
=== Reservation Confirmed ===
Guest: Emma Davis
Room: 310
Nights: 2
Requests: No special requests
Arrival: nullSpickzettel
Nicht-nullable Felder müssen initialisiert werden, bevor der Konstruktor-Body ausgeführt wird, während nullable Felder uninitialisiert bleiben können (Standardwert ist null):
class User {
String name; // Must be initialized
String? bio; // Optional - defaults to null
int age = 0; // Has default value
User(this.name);
}Verwenden Sie nullable Felder für optionale Daten:
class Product {
String title;
String? description; // Optional
double? discount; // Optional
Product(this.title);
}
var item = Product('Laptop');
print(item.description); // nullGreifen Sie auf nullable Felder mit Null-aware-Operatoren zu:
class Order {
String id;
User? customer;
Order(this.id);
String getCustomerName() {
return customer?.name ?? 'Guest';
}
}Verwenden Sie das Schlüsselwort required in benannten Parametern für essenzielle Werte:
class Account {
String email;
String? phone;
Account({required this.email, this.phone});
}
var acc = Account(email: 'test@mail.com');Probier es selbst
import 'reservation.dart';
void main() {
// TODO: Reservierung für 'Sarah Johnson' erstellen
// Zimmer 101, 3 Nächte, Sonderwünsche: 'Late checkout'
// Check-in-Zeit: DateTime(2024, 6, 15, 14, 30)
// TODO: Reservierung für 'Mike Chen' erstellen
// Zimmer 205, Standardanzahl an Nächten verwenden, Sonderwünsche: 'Extra pillows'
// Keine Check-in-Zeit angegeben
// TODO: Reservierung für 'Emma Davis' erstellen
// Zimmer 310, 2 Nächte, keine Sonderwünsche, keine Check-in-Zeit
// TODO: Für jede Reservierung in der Reihenfolge:
// 1. printConfirmation() aufrufen
// 2. 'Arrival: [result]' mit getArrivalInfo() ausgeben
}
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