extends în Dart

Creează o subclasă care moștenește câmpurile și metodele altei clase și le poate înlocui.

Sintaxă
class Copil extends Parinte {
  Copil(...) : super(...);

  @override
  Tip metoda() { ... }      // înlocuiește metoda moștenită
}

Ce face extends

class Caine extends Animal face din Caine o subclasă a lui Animal: primește toate câmpurile și metodele lui Animal (în afară de constructori) și poate adăuga altele noi. Un Caine poate fi folosit oriunde se așteaptă un Animal.

O metodă moștenită se poate înlocui scriind una cu același nume, marcată cu @override. Adnotarea nu este obligatorie, dar ajută: analizorul te avertizează dacă metoda nu există de fapt în clasa părinte. Versiunea originală se poate chema cu super.metoda().

O clasă are un singur părinte (moștenire simplă). Dacă nu scrii extends, părintele este Object. Pentru a combina comportamente din mai multe surse folosește implements sau mixin-uri (with).

Exemple

Exemplul 1: Subclasă care adaugă și înlocuiește

Student moștenește nume și prezinta și o înlocuiește pe cea din urmă.

class Persoana {
  final String nume;
  Persoana(this.nume);

  void prezinta() => print('Sunt $nume.');
}

class Student extends Persoana {
  final String facultate;
  Student(super.nume, this.facultate);

  @override
  void prezinta() => print('Sunt $nume, student la $facultate.');
}

void main() {
  Persoana('Ion').prezinta();
  Student('Ana', 'Informatică').prezinta();
}

Rezultat

Sunt Ion.
Sunt Ana, student la Informatică.

Exemplul 2: Polimorfism: o listă de tipuri diferite

Lista are tipul List<Angajat>, dar fiecare obiect folosește propria variantă a lui salariu.

class Angajat {
  final String nume;
  Angajat(this.nume);
  double salariu() => 4000;
}

class Manager extends Angajat {
  Manager(super.nume);
  @override
  double salariu() => super.salariu() * 1.5;
}

class Stagiar extends Angajat {
  Stagiar(super.nume);
  @override
  double salariu() => 2500;
}

void main() {
  final echipa = <Angajat>[Angajat('Dan'), Manager('Irina'), Stagiar('Tudor')];
  for (final a in echipa) {
    print('${a.nume} (${a.runtimeType}): ${a.salariu()} lei');
  }
}

Rezultat

Dan (Angajat): 4000.0 lei
Irina (Manager): 6000.0 lei
Tudor (Stagiar): 2500.0 lei

Exemplul 3: Lanțul de moștenire

is arată că un Pisica este și Mamifer, și Animal, și Object.

class Animal {
  String sunet() => '...';
}

class Mamifer extends Animal {}

class Pisica extends Mamifer {
  @override
  String sunet() => 'Miau';
}

void main() {
  Object tom = Pisica();
  print(tom is Mamifer);
  print(tom is Animal);
  if (tom is Animal) {
    print(tom.sunet());
  }
}

Rezultat

true
true
Miau

Greșeli frecvente

  • class A extends B, C: eroare, o clasă are un singur părinte. Folosește with sau implements.
  • Subclasă fără constructor potrivit când părintele nu are constructor fără parametri: eroarea The implicitly invoked unnamed constructor from 'Persoana' has required parameters. Apelează super(...) sau folosește parametri super.nume.
  • Lipsa lui @override: o greșeală de scriere în numele metodei creează o metodă nouă, iar cea veche rămâne neschimbată.

Comenzi înrudite

  • super: Accesează clasa părinte: constructorul ei (în lista de inițializare) sau metodele pe care subclasa le-a înlocuit.
  • implements: O clasă promite că are toți membrii altor clase (interfețe) și îi scrie singură, fără să moștenească codul lor.
  • mixin și with: Un mixin este un pachet de metode și câmpuri pe care îl adaugi în mai multe clase cu with, fără moștenire.
  • abstract: O clasă abstractă nu poate fi instanțiată direct; definește ce trebuie să facă subclasele ei.
  • covariant: Permite unei metode suprascrise să ceară un parametru de un tip mai restrâns decât în clasa părinte.