Approfondimento su getter e setter
Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 33 di 110.
I getter e i setter diventano potenti strumenti per l’incapsulamento quando vengono combinati con campi privati. Ti consentono di esporre un’interfaccia pubblica chiara mantenendo il pieno controllo su come i dati vengono consultati e modificati.
Uno schema comune consiste nell'abbinare un campo privato a un getter pubblico e a un setter che include una convalida:
class Temperature {
double _celsius = 0;
double get celsius => _celsius;
set celsius(double value) {
if (value < -273.15) {
_celsius = -273.15; // Minimo dello zero assoluto
} else {
_celsius = value;
}
}
}I setter possono far rispettare le regole di business, assicurandosi che il tuo oggetto non si trovi mai in uno stato non valido.
Puoi anche creare getter calcolati che ricavano valori da dati privati:
class Rectangle {
double _width;
double _height;
Rectangle(this._width, this._height);
double get area => _width * _height; // Calcolato
double get perimeter => 2 * (_width + _height);
double get width => _width;
set width(double value) {
if (value > 0) _width = value;
}
}A volte vuoi un accesso in sola lettura. Basta fornire un getter senza setter:
class Order {
final DateTime _createdAt = DateTime.now();
DateTime get createdAt => _createdAt; // Di sola lettura
}Questo schema consente al codice esterno di accedere ai dati impedendo al contempo qualsiasi modifica: il campo privato, combinato con un solo getter, garantisce un vero accesso in sola lettura.
Sfida
FacileCostruiamo un sistema di inventario prodotti che mostri la potenza di getter e setter per controllare l’accesso ai dati. Creerai una classe che protegge i propri dati interni, fornendo al contempo proprietà calcolate e convalida.
Organizzerai il codice in due file:
product.dart: definisci una classeProductche gestisce l’inventario con un corretto incapsulamento. Il prodotto dovrà avere:- Un
String namepubblico - Un
double _priceprivato - Un
int _quantityprivato - Un costruttore che accetta tutti e tre i valori
- Un getter
priceche restituisce il prezzo privato - Un setter
priceche accetta solo valori maggiori di0(ignora i valori non validi) - Un getter
quantityche restituisce la quantità privata - Un setter
quantityche accetta solo valori pari o superiori a0(ignora i valori negativi) - Un getter calcolato
totalValueche restituisce_price * _quantity - Un getter calcolato
isInStockche restituiscetruese la quantità è maggiore di0 - Un getter di sola lettura
skuche genera uno SKU semplice restituendo i primi 3 caratteri del nome in maiuscolo, seguiti dalla quantità (ad es.,LAP25per "Laptop" con quantità 25) - Un metodo
displayProduct()che mostra i dettagli del prodotto
- Un
main.dart: importa la classe del prodotto e mostra come i getter e i setter controllano l’accesso:- Crea un prodotto chiamato
'Laptop'con prezzo999.99e quantità25 - Chiama
displayProduct() - Stampa
In stock: [isInStock] - Stampa
SKU: [sku] - Prova a impostare il prezzo su
-50.0(dovrebbe essere ignorato) - Imposta il prezzo su
899.99(modifica valida) - Prova a impostare la quantità su
-10(dovrebbe essere ignorata) - Imposta la quantità su
0(modifica valida) - Chiama
displayProduct() - Stampa
In stock: [isInStock] - Stampa
SKU: [sku]
- Crea un prodotto chiamato
Il metodo displayProduct() dovrebbe stampare nel formato seguente:
--- Product Info ---
Name: [name]
Price: $[price]
Quantity: [quantity]
Total Value: $[totalValue]Output previsto:
--- Product Info ---
Name: Laptop
Price: $999.99
Quantity: 25
Total Value: $24999.75
In stock: true
SKU: LAP25
--- Product Info ---
Name: Laptop
Price: $899.99
Quantity: 0
Total Value: $0.0
In stock: false
SKU: LAP0Provalo tu
import 'product.dart';
void main() {
// TODO: Crea un prodotto chiamato 'Laptop' con prezzo 999.99 e quantità 25
// TODO: Chiama displayProduct()
// TODO: Stampa "In stock: [isInStock]"
// TODO: Stampa "SKU: [sku]"
// TODO: Prova a impostare il prezzo a -50.0 (deve essere ignorato)
// TODO: Imposta il prezzo a 899.99 (modifica valida)
// TODO: Prova a impostare la quantità a -10 (deve essere ignorata)
// TODO: Imposta la quantità a 0 (modifica valida)
// TODO: Chiama displayProduct()
// TODO: Stampa "In stock: [isInStock]"
// TODO: Stampa "SKU: [sku]"
}
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