base în Dart

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

Sintaxă
base class Nume { ... }         // se poate extinde, nu și implementa (în alt fișier)
base class Copil extends Nume {}  // subclasele trebuie să fie base, final sau sealed
base mixin Nume { ... }

Ce face base

base class garantează că orice obiect de tipul ei a trecut prin constructorul ei și are implementarea ei: alte biblioteci o pot extinde (extends), dar nu o pot implementa (implements) cu o altă implementare, „falsă”.

Pentru ca garanția să nu se piardă mai jos în ierarhie, orice subclasă a unei clase base trebuie marcată la rândul ei base, final sau sealed.

Este util când clasa are câmpuri private sau invarianți pe care metodele ei se bazează (de exemplu, un sold care nu poate deveni negativ). Ca la toți modificatorii, restricția se aplică doar din alt fișier.

Exemple

Exemplul 1: Clasă base extinsă de o subclasă base

ContEconomii trebuie declarată base; moștenește depune și regulile lui Cont.

base class Cont {
  double _sold = 0;
  double get sold => _sold;

  void depune(double suma) {
    if (suma <= 0) throw ArgumentError('suma trebuie să fie pozitivă');
    _sold += suma;
  }
}

base class ContEconomii extends Cont {
  void adaugaDobanda(double procent) => depune(sold * procent / 100);
}

void main() {
  final c = ContEconomii();
  c.depune(2000);
  c.adaugaDobanda(5);
  print('Sold: ${c.sold} lei');
}

Rezultat

Sold: 2100.0 lei

Exemplul 2: Implementarea și subclasele fără modificator, din alt fișier

conturi.dart declară base class Cont. Din main.dart, implements este interzis, iar o subclasă fără base/final/sealed la fel.

// conturi.dart
base class Cont {
  double sold = 0;
}

// main.dart
import 'conturi.dart';

class ContFals implements Cont {     // interzis: implementare
  @override
  double sold = 0;
}

class ContEconomii extends Cont {}  // interzis: lipsește base

base class ContCurent extends Cont {}  // permis

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

  error - main.dart:3:7 - The type 'ContFals' must be 'base', 'final' or 'sealed' because the supertype 'Cont' is 'base'. - subtype_of_base_or_final_is_not_base_final_or_sealed
  error - main.dart:3:27 - The class 'Cont' can't be implemented outside of its library because it's a base class. - invalid_use_of_type_outside_library
  error - main.dart:8:7 - The type 'ContEconomii' must be 'base', 'final' or 'sealed' because the supertype 'Cont' is 'base'. - subtype_of_base_or_final_is_not_base_final_or_sealed

Greșeli frecvente

  • Subclasă a unei clase base fără modificator: must be 'base', 'final' or 'sealed'.
  • Să folosești base când vrei să interzici și extinderea: pentru asta există final class.
  • Să crezi că base blochează ceva în același fișier: restricția se aplică doar altor biblioteci.

Comenzi înrudite

  • final class: Modificator de clasă (Dart 3): clasa nu poate fi extinsă și nici implementată în afara fișierului ei.
  • interface: Modificator de clasă (Dart 3): în afara fișierului ei, clasa poate fi doar implementată, nu și extinsă.
  • sealed: Clasă cu un set închis de subtipuri, toate în același fișier; switch-ul pe ea verifică dacă ai tratat toate cazurile.
  • extends: Creează o subclasă care moștenește câmpurile și metodele altei clase și le poate înlocui.