Modificatori de Clasă în Dart 3: sealed, final, base, interface și mixin class pentru Ierarhii Controlate în Dart

Ghid complet pentru noii modificatori de clasă introduși în Dart 3: diferențele între sealed, final, base, interface și mixin class, controlul subclasării în afara librăriei și verificarea exhaustivă în switch.

Sintaxă
sealed class UiState {} base class Repository {} interface class Service {}

Înainte de Dart 3.0, orice clasă din Dart putea fi simultan extinsă (extends), implementată ca interfață (implements) sau folosită drept mixin (with). Această libertate extremă crea riscuri majore pentru autorii de biblioteci și arhitecți software: era imposibil de garantat că o clasă nu este extinsă accidental de către clienți, rupând contractele interne la actualizări viitoare.

Dart 3 introduce o suită de modificatori de clasă care permit controlul riguros al operațiilor permise în afara librăriei curente (în afara aceluiași fișier sau pachet).

Sealed Classes și Verificarea Exhaustivă în Switch
// O clasă sealed poate fi subclasată EXCLUSIV în același fișier!
sealed class NetworkResult {}

class Success extends NetworkResult {
  final T data;
  Success(this.data);
}

class Failure extends NetworkResult {
  final String error;
  Failure(this.error);
}

class Loading extends NetworkResult {}

// Compilatorul GARANTEAZĂ exhaustivitatea: nu este nevoie de clauză default!
String handleResult(NetworkResult result) => switch (result) {
  Success(:final data) => 'Date primite: $data',
  Failure(:final error) => 'Eroare raportată: $error',
  Loading() => 'Se încarcă...'
  // Dacă adăugați o nouă subclasă în fișier și uitați un caz aici,
  // compilatorul va refuza să compileze proiectul!
};

Matricea Modificatorilor de Clasă în Dart 3 (În afara librăriei proprii)

Modificator Poate fi Instanțiată? Poate fi Extinsă (extends)? Poate fi Implementată (implements)? Poate fi Mixată (with)?
sealed Nu (este abstractă) Doar în același fișier Doar în același fișier Nu
final Da Nu Nu Nu
base Da Da (subclasa trebuie să fie tot base/final) Nu Nu
interface Da Nu Da Nu
mixin class Da Da Da Da
Exemplu: Utilizarea interface class și base class
// 1. interface class: Forțează implementarea completă, interzicând moștenirea de cod
interface class PaymentGateway {
  void processPayment(double amount) {
    print('Procesare implicită');
  }
}

// În alt fișier/pachet:
// ❌ class StripeGateway extends PaymentGateway {} // EROARE DE COMPILARE!
//  class StripeGateway implements PaymentGateway { ... } // PERMIS!

// 2. base class: Garantează că metodele clasei de bază sunt moștenite fizic
base class EventLogger {
  void log(String message) => print('[LOG]: $message');
}

// Subclasa trebuie să declare explicit 'base', 'final' sau 'sealed'
base class FileLogger extends EventLogger {
  @override
  void log(String message) {
    super.log(message);
    // Scriere suplimentară în fișier...
  }
}