Final & Const Felder
Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy — Lektion 18 von 110.
Beim Deklarieren von Feldern in einer Klasse können Sie final oder const verwenden, um zu steuern, ob sich Werte nach der Initialisierung ändern können. Beide erstellen unveränderliche Werte, aber sie funktionieren unterschiedlich.
Ein final-Feld kann nur einmal gesetzt werden, aber sein Wert wird zur Laufzeit bestimmt. Sie können es in der Deklaration oder über einen Konstruktor zuweisen:
class Person {
final String name;
final DateTime createdAt = DateTime.now();
Person(this.name);
}
Person p = Person('Alice');
// p.name = 'Bob'; // Fehler: Finales Feld kann nicht erneut zugewiesen werdenDer name wird gesetzt, wenn das Objekt erstellt wird, und createdAt erfasst die aktuelle Zeit. Beide Werte sind nach der Initialisierung gesperrt.
Ein static const Feld muss einen Wert haben, der zur Kompilierzeit bekannt ist. Es gehört zur Klasse selbst und wird von allen Instanzen gemeinsam genutzt:
class Circle {
static const double pi = 3.14159;
final double radius;
Circle(this.radius);
double get area => Circle.pi * radius * radius;
}Der entscheidende Unterschied: final-Felder können Werte enthalten, die zur Laufzeit berechnet werden (wie DateTime.now()), während const Kompilierzeit-Konstanten erfordert. Instanzfelder können nicht direkt const sein – auf Klassenebene ist nur static const zulässig.
Aufgabe
EinfachLassen Sie uns ein Produktkatalog-System erstellen, das den Unterschied zwischen final und static const Feldern demonstriert. Sie werden Produkte mit unveränderlichen Eigenschaften und gemeinsam genutzten Konfigurationswerten erstellen.
Sie werden Ihren Code in zwei Dateien organisieren:
product.dart: Definieren Sie eineProduct-Klasse, die einen Artikel in einem Geschäft repräsentiert. Ihre Klasse sollte Folgendes enthalten:- Ein
static const double taxRate, gesetzt auf0.08(8 % Steuersatz, der für alle Produkte gilt) - Ein
static const String currency, gesetzt auf'USD' - Ein
final String namefür den Produktnamen (gesetzt über den Konstruktor) - Ein
final double basePricefür den Basispreis des Produkts (gesetzt über den Konstruktor) - Ein
final String sku(Stock Keeping Unit), das ein Präfix mit dem Produktnamen kombiniert, berechnet in einer Initialisierungsliste als'SKU-'gefolgt vom Namen in Großbuchstaben - Einen Konstruktor, der
nameundbasePriceentgegennimmt - Einen Getter
priceWithTax, der den Preis inklusive Steuern berechnet - Eine
display()-Methode, die die Produktinformationen ausgibt
- Ein
main.dart: Importieren Sie Ihre Produktklasse und erstellen Sie zwei Produkte:- Einen
'Laptop'mit dem Basispreis999.99 - Eine
'Mouse'mit dem Basispreis29.99
display()für jedes Produkt in der oben aufgeführten Reihenfolge auf.- Einen
Die display()-Methode sollte in genau diesem Format drucken:
[sku] - [name]: [basePrice] [currency] (with tax: [priceWithTax] [currency])Runden Sie priceWithTax beim Anzeigen mit toStringAsFixed(2) auf 2 Dezimalstellen.
Erwartete Ausgabe:
SKU-LAPTOP - Laptop: 999.99 USD (with tax: 1079.99 USD)
SKU-MOUSE - Mouse: 29.99 USD (with tax: 32.39 USD)Spickzettel
Verwenden Sie final für Felder, die zur Laufzeit einmal gesetzt werden und danach nicht mehr geändert werden können. Verwenden Sie static const für Konstanten zur Kompilierzeit, die von allen Instanzen einer Klasse gemeinsam genutzt werden.
final-Felder werden zur Laufzeit gesetzt und können in der Deklaration oder im Konstruktor initialisiert werden:
class Person {
final String name;
final DateTime createdAt = DateTime.now();
Person(this.name);
}static const-Felder müssen Konstanten zur Kompilierzeit sein und gehören zur Klasse selbst:
class Circle {
static const double pi = 3.14159;
final double radius;
Circle(this.radius);
double get area => Circle.pi * radius * radius;
}Sie können Werte für final-Felder in einer Initialisierungsliste berechnen:
class Product {
final String name;
final String sku;
Product(this.name) : sku = 'SKU-${name.toUpperCase()}';
}Wichtige Unterschiede:
final: Laufzeitwerte, können für jede Instanz unterschiedlich seinstatic const: Konstanten zur Kompilierzeit, werden von allen Instanzen gemeinsam genutzt- Instanzfelder können nicht direkt
constsein – nurstatic constist zulässig
Probier es selbst
import 'product.dart';
void main() {
// TODO: Erstelle ein Product namens 'Laptop' mit einem Basispreis von 999.99
// TODO: Erstelle ein Product namens 'Mouse' mit einem Basispreis von 29.99
// TODO: Rufe display() für jedes Produkt in der richtigen Reihenfolge auf (zuerst Laptop, dann Mouse)
}
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