Ce face pattern-uri (destructurare)
Un pattern descrie forma unei valori. Folosit într-o declarație (final (nume, varsta) = elev;), el destructurează valoarea: scoate părțile ei în variabile noi. Funcționează cu records, liste ([a, b, ...rest]), map-uri ({'cheie': v}) și obiecte (Punct(:x, :y), care citește getter-ele x și y).
Pattern-urile apar și în buclele for-in (for (final MapEntry(:key, :value) in map.entries)), în switch și în if-case. Acolo pot și verifica: if (date case {'varsta': int v}) intră în bloc doar dacă map-ul are cheia și valoarea este int.
Într-o declarație, pattern-ul trebuie să se potrivească sigur (altfel apare o excepție la rulare); când datele pot avea altă formă, folosește if-case sau switch. Cu _ ignori o parte, iar (a, b) = (b, a); schimbă două variabile între ele.
Exemple
Exemplul 1: Destructurarea unui record și interschimbare
Patru variabile dintr-o singură declarație, apoi schimbarea valorilor fără variabilă temporară.
(String, String, int) citesteElev() => ('Ioana', 'Popa', 16);
void main() {
final (prenume, nume, varsta) = citesteElev();
print('$prenume $nume, $varsta ani');
final (_, numeFamilie, _) = citesteElev();
print('Doar numele de familie: $numeFamilie');
var a = 'stânga', b = 'dreapta';
(a, b) = (b, a);
print('a=$a, b=$b');
}
Rezultat
Ioana Popa, 16 ani
Doar numele de familie: Popa
a=dreapta, b=stânga
Exemplul 2: Liste, map-uri și obiecte
...rest prinde restul listei; pattern-ul de map citește cheile; MapEntry(:key, :value) desface fiecare intrare.
void main() {
final clasament = ['Ana', 'Mihai', 'Elena', 'Radu'];
final [castigator, locul2, ...ceilalti] = clasament;
print('Câștigător: $castigator, locul 2: $locul2, alții: $ceilalti');
final adresa = {'oras': 'Sibiu', 'strada': 'Bălcescu', 'numar': 12};
final {'oras': oras, 'numar': numar} = adresa;
print('$oras, nr. $numar');
final stoc = {'mere': 40, 'pere': 15};
for (final MapEntry(key: fruct, :value) in stoc.entries) {
print('$fruct: $value kg');
}
}
Rezultat
Câștigător: Ana, locul 2: Mihai, alții: [Elena, Radu]
Sibiu, nr. 12
mere: 40 kg
pere: 15 kg
Exemplul 3: Verificare cu if-case
Datele vin dintr-o sursă nesigură; blocul rulează doar când forma și tipurile se potrivesc.
void proceseaza(Object? date) {
if (date case {'nume': String nume, 'note': [int prima, ...]}) {
print('$nume are prima notă $prima');
} else if (date case [String oras, int temperatura]) {
print('În $oras sunt $temperatura °C');
} else {
print('Format necunoscut: $date');
}
}
void main() {
proceseaza({'nume': 'Andrei', 'note': [9, 10]});
proceseaza(['Galați', 23]);
proceseaza({'nume': 'Andrei'});
}
Rezultat
Andrei are prima notă 9
În Galați sunt 23 °C
Format necunoscut: {nume: Andrei}
Greșeli frecvente
- Un pattern de listă cu altă lungime într-o declarație:
final [a, b] = [1, 2, 3];aruncăStateErrorla rulare. Adaugă...sau foloseșteif-case. - Să crezi că pattern-ul de map cere toate cheile:
{'oras': o}se potrivește și dacă map-ul are alte chei în plus. Punct(:x)pentru un câmp privat sau inexistent: pattern-ul de obiect folosește getter-ele publice ale clasei.
Comenzi înrudite
records: Grupuri de valori anonime și imutabile, de forma (a, b) sau (nume: a), ideale pentru a întoarce mai multe valori.switch: Alege un bloc de cod după valoarea sau forma unei expresii; în Dart 3 fiecare case este un pattern.expresii switch: Forma de switch care produce o valoare: fiecare ramură este pattern => expresie.when (guard): Adaugă o condiție suplimentară la un pattern din switch sau if-case; cazul se alege doar dacă e adevărată.for-in: Parcurge pe rând elementele unei liste, unui set sau oricărui Iterable, fără indice.sealed: Clasă cu un set închis de subtipuri, toate în același fișier; switch-ul pe ea verifică dacă ai tratat toate cazurile.