sealed în Dart

Clasă cu un set închis de subtipuri, toate în același fișier; switch-ul pe ea verifică dacă ai tratat toate cazurile.

Sintaxă
sealed class Rezultat {}
class Succes extends Rezultat { ... }
class Eroare extends Rezultat { ... }

switch (rezultat) {
  case Succes(): ...
  case Eroare(): ...    // analizorul verifică că ai tratat toate subtipurile
}

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ă sealed este 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 default sau _ în switch-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.