Öffentliche vs. private Member
Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy — Lektion 30 von 110.
Kapselung ist eines der Kernprinzipien der objektorientierten Programmierung. Es geht darum, den Zugriff auf die internen Daten einer Klasse zu steuern und zu entscheiden, was nach außen hin sichtbar sein soll und was verborgen bleiben muss.
In Dart sind Klassenmitglieder (Felder und Methoden) standardmäßig öffentlich. Das bedeutet, dass jeder Code direkt auf sie zugreifen kann:
class BankAccount {
String owner;
double balance;
BankAccount(this.owner, this.balance);
}
var account = BankAccount('Alice', 1000);
account.balance = -500; // Jeder kann dies direkt ändern!Das ist problematisch. Nichts verhindert das Festlegen eines ungültigen Kontostands.
Um interne Daten zu schützen, verwendet Dart private Member. Ein Member wird privat, wenn sein Name mit einem Unterstrich _ beginnt:
class BankAccount {
String owner;
double _balance; // Privat - beginnt mit Unterstrich
BankAccount(this.owner, this._balance);
double get balance => _balance; // Kontrollierter Zugriff
}Jetzt kann auf _balance nicht mehr direkt von außerhalb der Bibliothek zugegriffen werden, in der die Klasse definiert ist. Externer Code muss stattdessen den öffentlichen Getter verwenden. Dies ermöglicht es Ihnen zu kontrollieren, wie Daten gelesen und geändert werden, und stellt sicher, dass Ihre Objekte immer in einem gültigen Zustand bleiben.
Aufgabe
EinfachLassen Sie uns einen einfachen Passwort-Manager erstellen, der den Unterschied zwischen öffentlichen und privaten Membern demonstriert. Sie werden sehen, wie das Unterstrich-Präfix sensible Daten davor schützt, direkt von außerhalb der Bibliothek der Klasse aufgerufen zu werden.
Sie werden zwei Dateien erstellen, um Ihren Code zu organisieren:
credential.dart: Definieren Sie eineCredential-Klasse, die Login-Informationen für eine Website speichert. Die Klasse sollte Folgendes enthalten:- Einen öffentlichen
String website- es ist in Ordnung, wenn jeder sieht, für welche Website dies ist - Einen öffentlichen
String username- der Benutzername kann sichtbar sein - Einen privaten
String _password- das tatsächliche Passwort muss geschützt werden - Einen Konstruktor, der alle drei Werte entgegennimmt
- Einen öffentlichen Getter
password, der das private_passwordzurückgibt (kontrollierter Zugriff) - Eine Methode
getMaskedPassword(), die das Passwort zurückgibt, wobei alle Zeichen durch Sternchen*ersetzt sind (gleiche Länge wie das tatsächliche Passwort) - Eine Methode
displayCredential(), welche die Anmeldedaten sicher ausgibt (indem sie das maskierte Passwort anzeigt, nicht das echte)
- Einen öffentlichen
main.dart: Importieren Sie Ihre Credential-Klasse und demonstrieren Sie, wie Kapselung das Passwort schützt:- Erstellen Sie ein Credential für die Website
'github.com', den Benutzernamen'dev_user'und das Passwort'secret123' - Erstellen Sie ein weiteres Credential für die Website
'email.com', den Benutzernamen'john_doe'und das Passwort'myP@ss' - Rufen Sie für jedes Credential
displayCredential()auf und geben Sie dannActual password length: [length]aus, wobei Sie den öffentlichen Getter verwenden, um auf die Länge des Passworts zuzugreifen
- Erstellen Sie ein Credential für die Website
Die Methode displayCredential() sollte in diesem Format drucken:
--- Credential ---
Website: [website]
Username: [username]
Password: [maskedPassword]Erwartete Ausgabe:
--- Credential ---
Website: github.com
Username: dev_user
Password: *********
Actual password length: 9
--- Credential ---
Website: email.com
Username: john_doe
Password: ******
Actual password length: 6Spickzettel
Kapselung steuert den Zugriff auf die internen Daten einer Klasse, indem sie entscheidet, was sichtbar sein soll und was verborgen bleiben soll.
In Dart sind Klassenmitglieder standardmäßig öffentlich:
class BankAccount {
String owner;
double balance; // Öffentlich - direkter Zugriff möglich
BankAccount(this.owner, this.balance);
}
var account = BankAccount('Alice', 1000);
account.balance = -500; // Direkte Änderung erlaubtUm interne Daten zu schützen, verwenden Sie private Mitglieder, indem Sie dem Namen einen Unterstrich _ voranstellen:
class BankAccount {
String owner;
double _balance; // Privat - beginnt mit Unterstrich
BankAccount(this.owner, this._balance);
double get balance => _balance; // Kontrollierter Zugriff über Getter
}Auf private Mitglieder kann nicht direkt von außerhalb der Bibliothek zugegriffen werden, in der die Klasse definiert ist. Verwenden Sie öffentliche Getter und Methoden, um einen kontrollierten Zugriff auf private Daten zu ermöglichen und sicherzustellen, dass Objekte in einem gültigen Zustand bleiben.
Probier es selbst
import 'credential.dart';
void main() {
// TODO: Erstelle ein Credential für github.com
// website: 'github.com', username: 'dev_user', password: 'secret123'
// TODO: Rufe displayCredential() für das erste Credential auf
// TODO: Gib die tatsächliche Passwortlänge über den öffentlichen Getter aus
// Format: "Actual password length: [length]"
// TODO: Erstelle ein Credential für email.com
// website: 'email.com', username: 'john_doe', password: 'myP@ss'
// TODO: Rufe displayCredential() für das zweite Credential auf
// TODO: Gib die tatsächliche Passwortlänge über den öffentlichen Getter 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 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