super în Dart

Moștenire, mixin-uri și modificatori de clasă Dart 1.0 (parametri super.camp din Dart 2.17)

Accesează clasa părinte: constructorul ei (în lista de inițializare) sau metodele pe care subclasa le-a înlocuit.

Sintaxă
Copil(Tip a, Tip b) : super(a);        // apelează constructorul părintelui
Copil(super.a, this.b);                // parametru super (Dart 2.17)
Copil.numit() : super.numit();
super.metoda();                        // varianta metodei din părinte

Ce face super

Într-o subclasă, constructorul trebuie să apeleze un constructor al părintelui, ca partea moștenită a obiectului să fie inițializată. Apelul se scrie la sfârșitul listei de inițializare: : super(nume). Dacă lipsește, Dart apelează automat super() fără argumente.

Din Dart 2.17 există parametri super: Student(super.nume, this.facultate); trimite direct argumentul la constructorul părintelui, fără să-l scrii de două ori.

În metode, super.metoda() cheamă varianta din părinte a unei metode pe care ai suprascris-o. Așa extinzi comportamentul în loc să-l rescrii de la zero.

Exemple

Exemplul 1: Apelul constructorului părinte

Forma clasică cu : super(...) și forma scurtă cu parametri super. fac același lucru.

class Vehicul {
  final String marca;
  final int roti;
  Vehicul(this.marca, this.roti) {
    print('Vehicul $marca cu $roti roți');
  }
}

class Bicicleta extends Vehicul {
  Bicicleta(String marca) : super(marca, 2);
}

class Camion extends Vehicul {
  final double tone;
  Camion(super.marca, super.roti, this.tone);
}

void main() {
  Bicicleta('Pegas');
  final c = Camion('Roman', 6, 12.5);
  print('${c.marca} duce ${c.tone} tone.');
}

Rezultat

Vehicul Pegas cu 2 roți
Vehicul Roman cu 6 roți
Roman duce 12.5 tone.

Exemplul 2: Extinderea unei metode cu super

ContEconomii.descriere folosește textul din părinte și adaugă dobânda.

class Cont {
  final String titular;
  double sold;
  Cont(this.titular, this.sold);

  String descriere() => '$titular: ${sold.toStringAsFixed(2)} lei';
}

class ContEconomii extends Cont {
  final double dobanda;
  ContEconomii(super.titular, super.sold, this.dobanda);

  @override
  String descriere() => '${super.descriere()}, dobândă ${dobanda * 100}%';
}

void main() {
  print(Cont('Mihai', 850).descriere());
  print(ContEconomii('Elena', 12000, 0.05).descriere());
}

Rezultat

Mihai: 850.00 lei
Elena: 12000.00 lei, dobândă 5.0%

Exemplul 3: Ordinea de inițializare

Lista de inițializare a copilului rulează prima, apoi constructorul părintelui, apoi corpul copilului.

String log(String mesaj) {
  print(mesaj);
  return mesaj;
}

class Parinte {
  final String a;
  Parinte() : a = log('1. inițializare Părinte') {
    log('2. corp Părinte');
  }
}

class Copil extends Parinte {
  final String b;
  Copil() : b = log('0. inițializare Copil'), super() {
    log('3. corp Copil');
  }
}

void main() {
  Copil();
}

Rezultat

0. inițializare Copil
1. inițializare Părinte
2. corp Părinte
3. corp Copil

Greșeli frecvente

  • super(...) pus la începutul listei de inițializare, înaintea altor inițializări: eroare, apelul lui super trebuie să fie ultimul.
  • Apelul lui super(...) în corpul constructorului (ca în Java): în Dart se scrie doar în lista de inițializare.
  • Să amesteci un parametru super.nume cu un apel explicit super(nume) pentru același argument: argumentul ar fi transmis de două ori, iar analizorul dă eroare.

Comenzi înrudite

  • extends: Creează o subclasă care moștenește câmpurile și metodele altei clase și le poate înlocui.
  • constructori: Funcțiile speciale care creează și inițializează obiectele unei clase.
  • this: Referință la obiectul curent, în interiorul metodelor și constructorilor unei clase.
  • 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.