Gli operatori ? e !
Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 25 di 110.
Quando lavori con tipi nullable, Dart fornisce due operatori essenziali per accedere ai valori in modo sicuro. L'operatore di accesso null-aware ?. e l'operatore di asserzione non-null ! ti consentono di controllare come gestire i valori potenzialmente null.
L'operatore ?. accede in modo sicuro alle proprietà o ai metodi di un valore nullable. Se il valore è null, l'intera espressione restituisce null invece di causare un arresto anomalo:
String? name = 'Alice';
print(name?.length); // 5
name = null;
print(name?.length); // null (nessun crash!)L’operatore ! dice a Dart: «Sono certo che questo valore non sia null». Converte un tipo nullable in un tipo non nullable, ma genera un errore se il valore è effettivamente null:
String? maybeName = 'Bob';
String definite = maybeName!; // OK - affermiamo che non è null
print(definite.length); // 3
String? empty = null;
// String crash = empty!; // Errore a runtime! Il valore era nullUsa ?. quando vuoi gestire con eleganza i valori null. Usa ! solo quando sei assolutamente certo che un valore esista, magari dopo averlo verificato con un'istruzione if o quando sai che la logica garantisce un valore. Usare troppo ! vanifica lo scopo della sicurezza dai valori null e può causare arresti anomali in fase di esecuzione.
Sfida
FacileCreiamo un sistema di inventario dei prodotti che mostra come lavorare in sicurezza con valori nullable usando gli operatori ?. e !.
Creerai due file per organizzare il tuo codice:
product.dart: definisci una classeProductche rappresenta un articolo nell'inventario. Alcuni prodotti hanno informazioni complete, mentre altri sono ancora in fase di catalogazione. La tua classe dovrebbe avere:- Un
String namenon nullable: ogni prodotto deve avere un nome - Un
double pricenon nullable: ogni prodotto deve avere un prezzo - Un
String? descriptionnullable: alcuni prodotti non hanno ancora una descrizione - Un
String? categorynullable: alcuni prodotti non sono ancora stati categorizzati - Un costruttore che accetta
nameepricecome parametri obbligatori - Un metodo
getDescriptionLength()che restituisce la lunghezza della descrizione usando?., oppurenullse non c'è una descrizione - Un metodo
getCategoryUppercase()che restituisce la categoria in maiuscolo usando!: questo metodo presuppone che la categoria sia stata impostata - Un metodo
displayProduct()che stampa le informazioni sul prodotto, mostrandoNo descriptionquando la descrizione è null eUncategorizedquando la categoria è null
- Un
main.dart: importa la tua classe del prodotto e mostra entrambi gli operatori:- Crea un prodotto chiamato
'Laptop'con prezzo999.99, poi imposta la sua descrizione su'High-performance computing device'e la categoria su'Electronics' - Crea un prodotto chiamato
'Mystery Item'con prezzo49.99(lascia description e category impostati su null) - Per Laptop: chiama
displayProduct(), stampaDescription length: [length]usandogetDescriptionLength()e stampaCategory: [uppercase]usandogetCategoryUppercase() - Per Mystery Item: chiama
displayProduct()e stampaDescription length: [length]usandogetDescriptionLength()(verrà mostratonull)
- Crea un prodotto chiamato
Il metodo displayProduct() dovrebbe stampare nel seguente formato:
Product: [name] - $[price]
Description: [description or "No description"]
Category: [category or "Uncategorized"]Output previsto:
Product: Laptop - $999.99
Description: High-performance computing device
Category: Electronics
Description length: 32
Category: ELECTRONICS
Product: Mystery Item - $49.99
Description: No description
Category: Uncategorized
Description length: nullProvalo tu
import 'product.dart';
void main() {
// TODO: Crea un prodotto chiamato 'Laptop' con prezzo 999.99
// Poi imposta la sua descrizione su 'High-performance computing device'
// E imposta la sua categoria su 'Electronics'
// TODO: Crea un prodotto chiamato 'Mystery Item' con prezzo 49.99
// Lascia descrizione e categoria a null
// TODO: Per Laptop:
// - Chiama displayProduct()
// - Stampa "Description length: [length]" usando getDescriptionLength()
// - Stampa "Category: [uppercase]" usando getCategoryUppercase()
// TODO: Per Mystery Item:
// - Chiama displayProduct()
// - Stampa "Description length: [length]" usando getDescriptionLength()
}
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