Ce face sealed
O clasă sealed (sigilată) este automat abstractă și poate avea subtipuri doar în fișierul în care a fost declarată. Analizorul cunoaște astfel toate subtipurile posibile.
Avantajul mare: un switch pe o valoare de tip sigilat este verificat pentru exhaustivitate. Dacă tratezi Succes și Eroare, nu mai ai nevoie de default; iar dacă mai târziu adaugi subtipul InCurs, analizorul îți arată fiecare switch care trebuie completat.
Este modul obișnuit în Dart 3 de a modela stări („se încarcă”, „gata”, „eroare”), comenzi sau rezultate. Din alt fișier, o clasă sigilată nu poate fi extinsă, implementată sau folosită ca mixin.
Exemple
Exemplul 1: Stările unei comenzi
Expresia switch tratează toate cele trei subtipuri, fără default. Pattern-ul Livrata(:final oras) extrage și câmpul.
sealed class StareComanda {}
class Plasata extends StareComanda {}
class InLivrare extends StareComanda {
final int minute;
InLivrare(this.minute);
}
class Livrata extends StareComanda {
final String oras;
Livrata(this.oras);
}
String mesaj(StareComanda s) => switch (s) {
Plasata() => 'Comanda a fost primită.',
InLivrare(:final minute) => 'Curierul ajunge în $minute minute.',
Livrata(:final oras) => 'Comanda a fost livrată în $oras.',
};
void main() {
for (final s in [Plasata(), InLivrare(25), Livrata('Brașov')]) {
print(mesaj(s));
}
}
Rezultat
Comanda a fost primită.
Curierul ajunge în 25 minute.
Comanda a fost livrată în Brașov.
Exemplul 2: Rezultatul unei operații
imparte întoarce un Succes sau o Eroare, iar apelantul este obligat să trateze ambele variante.
sealed class Rezultat {}
class Succes extends Rezultat {
final double valoare;
Succes(this.valoare);
}
class Eroare extends Rezultat {
final String motiv;
Eroare(this.motiv);
}
Rezultat imparte(double a, double b) =>
b == 0 ? Eroare('împărțire la zero') : Succes(a / b);
void main() {
for (final (a, b) in [(150.0, 4.0), (10.0, 0.0)]) {
switch (imparte(a, b)) {
case Succes(:final valoare):
print('$a / $b = $valoare');
case Eroare(:final motiv):
print('$a / $b: $motiv');
}
}
}
Rezultat
150.0 / 4.0 = 37.5
10.0 / 0.0: împărțire la zero
Exemplul 3: Un caz uitat în switch
Am adăugat un subtip nou, Anulata, dar nu l-am tratat. Analizorul arată exact ce lipsește.
sealed class Stare {}
class Activa extends Stare {}
class Anulata extends Stare {}
String text(Stare s) => switch (s) {
Activa() => 'activă',
};
void main() {
print(text(Activa()));
}
Rezultatul lui dart analyze
error - main.dart:7:25 - The type 'Stare' isn't exhaustively matched by the switch cases since it doesn't match the pattern 'Anulata()'. Try adding a wildcard pattern or cases that match 'Anulata()'. - non_exhaustive_switch_expression
Greșeli frecvente
- Să încerci
Stare(): o clasăsealedeste abstractă și nu se poate instanția. - Subtipuri puse în alt fișier:
can't be extended, implemented, or mixed in outside of its library because it's a sealed class. - Un
defaultsau_înswitch-ul pe un tip sigilat: merge, dar pierzi avertizarea când adaugi un subtip nou.
Comenzi înrudite
expresii switch: Forma de switch care produce o valoare: fiecare ramură este pattern => expresie.pattern-uri (destructurare): Desfac o valoare (record, listă, map, obiect) în variabile separate, într-o singură declarație.switch: Alege un bloc de cod după valoarea sau forma unei expresii; în Dart 3 fiecare case este un pattern.abstract: O clasă abstractă nu poate fi instanțiată direct; definește ce trebuie să facă subclasele ei.final class: Modificator de clasă (Dart 3): clasa nu poate fi extinsă și nici implementată în afara fișierului ei.