constructori numiți în Dart

Constructori cu nume propriu (Clasa.nume), pentru mai multe moduri de a crea același tip de obiect.

Sintaxă
class Nume {
  Nume(...);                      // constructorul principal
  Nume.altNume(...) { ... }       // constructor numit
  Nume.scurt(int a) : this(a, 0); // redirecționează spre alt constructor
}

Nume.altNume(...);

Ce face constructori numiți

Pentru că Dart nu are supraîncărcare (doi constructori cu același nume și parametri diferiți), o clasă poate avea mai mulți constructori dându-le nume: Temperatura.dinFahrenheit(98.6), DateTime.utc(...), List.filled(3, 0). Numele spune clar ce face fiecare.

Un constructor numit poate redirecționa spre alt constructor al aceleiași clase cu : this(...); atunci nu are corp. Așa eviți să repeți codul de inițializare.

Constructorii numiți nu se moștenesc: dacă o subclasă vrea Produs.gratuit, trebuie să-și declare propriul constructor, care poate apela super.gratuit(...).

Exemple

Exemplul 1: Două moduri de a crea o temperatură

Constructorul principal primește grade Celsius, iar cel numit convertește din Fahrenheit.

class Temperatura {
  final double celsius;

  Temperatura(this.celsius);

  Temperatura.dinFahrenheit(double f) : celsius = (f - 32) * 5 / 9;

  @override
  String toString() => '${celsius.toStringAsFixed(1)} °C';
}

void main() {
  print(Temperatura(21.5));
  print(Temperatura.dinFahrenheit(98.6));
}

Rezultat

21.5 °C
37.0 °C

Exemplul 2: Redirecționare cu : this(…)

Produs.gratuit nu are corp: cheamă constructorul principal cu prețul 0.

class Produs {
  final String nume;
  final double pret;

  Produs(this.nume, this.pret);
  Produs.gratuit(String nume) : this(nume, 0);

  @override
  String toString() => pret == 0 ? '$nume: gratuit' : '$nume: $pret lei';
}

void main() {
  print(Produs('Caiet', 6.5));
  print(Produs.gratuit('Semn de carte'));
}

Rezultat

Caiet: 6.5 lei
Semn de carte: gratuit

Exemplul 3: Constructor dintr-un Map

Un tipar frecvent când datele vin din JSON: Elev.dinMap citește valorile din map.

class Elev {
  final String nume;
  final String clasa;
  final List<int> note;

  Elev(this.nume, this.clasa, this.note);

  Elev.dinMap(Map<String, dynamic> date)
      : nume = date['nume'] as String,
        clasa = date['clasa'] as String,
        note = List<int>.from(date['note'] as List);

  @override
  String toString() => '$nume ($clasa): $note';
}

void main() {
  final date = {'nume': 'Maria', 'clasa': 'a X-a B', 'note': [10, 9, 9]};
  print(Elev.dinMap(date));
}

Rezultat

Maria (a X-a B): [10, 9, 9]

Greșeli frecvente

  • Să încerci Punct(int x) și Punct(double x) în aceeași clasă: eroarea The unnamed constructor is already defined. Dă-i unuia un nume.
  • Un constructor care redirecționează cu : this(...) și are și corp sau alte inițializări: nu este permis.
  • Să aștepți ca subclasa să primească automat constructorii numiți ai clasei părinte: nu se moștenesc.

Comenzi înrudite

  • constructori: Funcțiile speciale care creează și inițializează obiectele unei clase.
  • factory: Constructor care nu creează neapărat un obiect nou: poate întoarce unul din cache sau o subclasă.
  • class: Definește un tip nou de obiect, cu câmpuri (date) și metode (comportament).