final class în Dart

Modificator de clasă (Dart 3): clasa nu poate fi extinsă și nici implementată în afara fișierului ei.

Sintaxă
final class Nume { ... }    // nu se poate extinde și nici implementa din alt fișier

Ce face final class

final class închide complet clasa pentru celelalte biblioteci: nu poate fi extinsă (extends), nu poate fi implementată (implements) și nu poate fi folosită ca mixin. Autorul ei o poate modifica oricând fără să strice codul altcuiva.

Nu confunda cu variabilele final: aici cuvântul se aplică unei clase și se referă la moștenire, nu la valori. Obiectele unei final class pot avea câmpuri modificabile.

În același fișier poți încă extinde clasa, dar subclasele trebuie să fie și ele base, final sau sealed.

Exemple

Exemplul 1: O clasă de valoare închisă

Cnp verifică formatul în constructor. Fiind final, nimeni din altă bibliotecă nu poate crea un „CNP” care ocolește verificarea.

final class Cnp {
  final String valoare;

  Cnp(this.valoare) {
    if (valoare.length != 13 || int.tryParse(valoare) == null) {
      throw FormatException('CNP-ul trebuie să aibă 13 cifre', valoare);
    }
  }

  String get sex => '1357'.contains(valoare[0]) ? 'masculin' : 'feminin';
}

void main() {
  print(Cnp('2950412123456').sex);
  try {
    Cnp('12345');
  } on FormatException catch (e) {
    print('${e.message}: ${e.source}');
  }
}

Rezultat

feminin
CNP-ul trebuie să aibă 13 cifre: 12345

Exemplul 2: Extinderea și implementarea din alt fișier

facturi.dart declară final class Factura. Din main.dart, ambele încercări sunt respinse.

// facturi.dart
final class Factura {
  final double total;
  Factura(this.total);
}

// main.dart
import 'facturi.dart';

class FacturaMea extends Factura {
  FacturaMea() : super(10);
}

class FacturaFalsa implements Factura {
  @override
  double get total => 0;
}

Rezultatul lui dart analyze (al doilea fișier nu se compilează)

  error - main.dart:3:26 - The class 'Factura' can't be extended outside of its library because it's a final class. - invalid_use_of_type_outside_library
  error - main.dart:7:31 - The class 'Factura' can't be implemented outside of its library because it's a final class. - invalid_use_of_type_outside_library

Greșeli frecvente

  • Să crezi că final class face obiectele imutabile: câmpurile rămân modificabile dacă nu sunt final.
  • Folosirea lui final class peste tot într-un pachet public: utilizatorii nu-ți mai pot crea implementări de test (mock-uri) cu implements.
  • O subclasă din același fișier fără base, final sau sealed: eroare.

Comenzi înrudite

  • base: Modificator de clasă (Dart 3): clasa poate fi extinsă, dar nu implementată în afara fișierului ei.
  • sealed: Clasă cu un set închis de subtipuri, toate în același fișier; switch-ul pe ea verifică dacă ai tratat toate cazurile.
  • interface: Modificator de clasă (Dart 3): în afara fișierului ei, clasa poate fi doar implementată, nu și extinsă.
  • final: Declară o variabilă care primește valoarea o singură dată și nu mai poate fi reatribuită.