Membri pubblici e privati
Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 30 di 110.
L'incapsulamento è uno dei principi fondamentali della programmazione orientata agli oggetti. Riguarda il controllo dell'accesso ai dati interni di una classe, decidendo cosa deve essere visibile all'esterno e cosa deve rimanere nascosto.
In Dart, i membri di una classe (campi e metodi) sono pubblici per impostazione predefinita. Ciò significa che qualsiasi codice può accedervi direttamente:
class BankAccount {
String owner;
double balance;
BankAccount(this.owner, this.balance);
}
var account = BankAccount('Alice', 1000);
account.balance = -500; // Chiunque può modificarlo direttamente!Questo è problematico. Nulla impedisce di impostare un saldo non valido.
Per proteggere i dati interni, Dart usa i membri privati. Un membro diventa privato quando il suo nome inizia con un trattino basso _:
class BankAccount {
String owner;
double _balance; // Privato - inizia con un trattino basso
BankAccount(this.owner, this._balance);
double get balance => _balance; // Accesso controllato
}Ora _balance non può essere consultato direttamente dall'esterno della libreria in cui è definita la classe. Il codice esterno deve usare invece il getter pubblico. Questo ti permette di controllare come vengono letti e modificati i dati, assicurandoti che i tuoi oggetti rimangano sempre in uno stato valido.
Sfida
FacileCostruiamo un semplice gestore di password che mostra la differenza tra membri pubblici e privati. Vedrai come il prefisso di sottolineatura protegge i dati sensibili dall'accesso diretto dall'esterno della libreria della classe.
Creerai due file per organizzare il codice:
credential.dart: definisci una classeCredentialche memorizza le informazioni di accesso a un sito web. La classe dovrebbe avere:- Un
String websitepubblico: va bene che chiunque possa vedere a quale sito web si riferisce - Un
String usernamepubblico: il nome utente può essere visibile - Un
String _passwordprivato: la password effettiva deve essere protetta - Un costruttore che accetta tutti e tre i valori
- Un getter pubblico
passwordche restituisce il_passwordprivato (accesso controllato) - Un metodo
getMaskedPassword()che restituisce la password sostituendo tutti i caratteri con asterischi*(della stessa lunghezza della password effettiva) - Un metodo
displayCredential()che stampa in modo sicuro le informazioni della credenziale (mostrando la password mascherata, non quella reale)
- Un
main.dart: importa la classe della credenziale e mostra come l'incapsulamento protegge la password:- Crea una credenziale per il sito web
'github.com', con nome utente'dev_user'e password'secret123' - Crea un'altra credenziale per il sito web
'email.com', con nome utente'john_doe'e password'myP@ss' - Per ogni credenziale, chiama
displayCredential(), quindi stampaActual password length: [length]usando il getter pubblico per accedere alla lunghezza della password
- Crea una credenziale per il sito web
Il metodo displayCredential() dovrebbe stampare in questo formato:
--- Credential ---
Website: [website]
Username: [username]
Password: [maskedPassword]Risultato previsto:
--- Credential ---
Website: github.com
Username: dev_user
Password: *********
Actual password length: 9
--- Credential ---
Website: email.com
Username: john_doe
Password: ******
Actual password length: 6Provalo tu
import 'credential.dart';
void main() {
// TODO: Crea una credenziale per github.com
// website: 'github.com', username: 'dev_user', password: 'secret123'
// TODO: Chiama displayCredential() sulla prima credenziale
// TODO: Stampa la lunghezza effettiva della password usando il getter pubblico
// Formato: "Actual password length: [length]"
// TODO: Crea una credenziale per email.com
// website: 'email.com', username: 'john_doe', password: 'myP@ss'
// TODO: Chiama displayCredential() sulla seconda credenziale
// TODO: Stampa la lunghezza effettiva della password usando il getter pubblico
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione orientata agli oggetti
File esterniLibrerie e importazioniIntroduzione alla programmazione orientata agli oggettiClassi e oggettiLa parola chiave thisMetodiVariabili di istanzaFondamenti dei costruttoriRiepilogo - Calcolatrice semplice4Sicurezza dei valori null
Introduzione alla sicurezza dei valori nullNullable e non nullableGli operatori ? e !La keyword late e la sicurezza dei valori nullOperatori null-awareSicurezza dei valori null nelle classiRiepilogo - Sistema di profili utente7Classi astratte e interfacce
Classi astratteMetodi astrattiInterfacce in DartInterfacce impliciteImplementare vs estendereInterfacce multipleRiepilogo - Calcolatore di forme10Collezioni e generici
Panoramica di List, Set e MapCollezioni sicure rispetto ai tipiClassi genericheMetodi genericiVincoli sui genericiIterable e IteratorRiepilogo - Archiviazione generica13Concetti avanzati di OOP
Composizione vs ereditarietàMetodi di estensioneClassi chiamabiliClassi sealed (Dart 3)Record (Dart 3)Pattern e matching (3.0)Enum con metodi16Progetto: Gestione della biblioteca
Panoramica del progettoClassi Libro e Utente2I costruttori in Dart
Costruttore predefinitoCostruttori con nomeListe di inizializzazioneCostruttori costantiCostruttori factoryCostruttori di reindirizzamentoRiepilogo - Crea forme5Incapsulamento
Membri pubblici e privatiConvenzione del prefisso _Visibilità a livello di libreriaApprofondimento su getter e setterNascondimento delle informazioniRiepilogo - Registri degli studenti8Mixin
Introduzione ai MixinCreare MixinUsare più MixinParola chiave on nei MixinMixin vs ereditarietàMixin vs interfacciaRiepilogo - Sistema animale11Metodi speciali
Sovrascrittura di toString()Sovrascrittura di hashCode e ==Interfaccia ComparableMetodo call()Sovrascrittura di noSuchMethodRiepilogo - Collezione personalizzata14Modelli di progettazione Parte 1
Introduzione ai modelli di progettazioneSingletonFactoryObserverStrategy3Proprietà delle classi
Membri di istanza e staticiCampi final e constVariabili lateMetodi e campi staticiGetter e setterRiepilogo - Gestore di conti bancari6Ereditarietà
Ereditarietà di baseLa parola chiave superOverride dei metodiL’annotazione @overrideLa parola chiave final per le classiCostruttori ed ereditarietàRiepilogo - Gerarchia dei dipendenti9Polimorfismo
Fondamenti di polimorfismoPolimorfismo tramite interfacceControllo del tipo a runtimeGli operatori is e asParola chiave covariantRiepilogo - Elaboratore di pagamenti12OOP asincrona
Future e async/awaitNozioni di base sugli streamController degli streamCostruttori asincroniAsync nei metodi di classeRiepilogo - Recupero dei dati15Pattern di progettazione Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositePattern RepositoryEsercitati da solo: Compilatore Dart online