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ștewithsauimplements.- 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 parametrisuper.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.