constructori în Dart

Clase și obiecte Dart 1.0 (parametri super din Dart 2.17)

Funcțiile speciale care creează și inițializează obiectele unei clase.

Sintaxă
class Punct {
  final int x, y;
  Punct(this.x, this.y);                       // parametri care inițializează câmpuri
  Punct.cuVerificare(int x, int y)
      : assert(x >= 0), x = x, y = y;          // listă de inițializare
  const Punct.fix(this.x, this.y);             // constructor const
}

Ce face constructori

Constructorul are același nume ca clasa și se apelează pentru a crea un obiect. Forma scurtă Elev(this.nume, this.varsta); copiază direct argumentele în câmpuri. Dacă nu scrii niciun constructor, Dart îți dă unul implicit, fără parametri.

Între ) și corpul constructorului poate sta o listă de inițializare, după :. Acolo poți calcula câmpuri final din argumente și poți pune assert-uri. Codul din listă rulează înainte ca obiectul să existe, deci acolo nu poți folosi this.

Un constructor const (toate câmpurile final) permite obiecte constante: const Culoare(255, 0, 0) este creat o singură dată, la compilare, și reutilizat. Parametrii pot fi și numiți ({required this.nume}) sau opționali cu valori implicite, exact ca la funcții.

Exemple

Exemplul 1: Parametri numiți și valori implicite

required obligă apelantul să dea numele; orașul are valoarea implicită „București”.

class Client {
  final String nume;
  final String oras;
  final int puncte;

  Client({required this.nume, this.oras = 'București', this.puncte = 0});

  @override
  String toString() => '$nume din $oras, $puncte puncte';
}

void main() {
  print(Client(nume: 'Ana'));
  print(Client(nume: 'Radu', oras: 'Iași', puncte: 120));
}

Rezultat

Ana din București, 0 puncte
Radu din Iași, 120 puncte

Exemplul 2: Listă de inițializare

media este final și se calculează din note înainte de corpul constructorului.

class Situatie {
  final String elev;
  final List<int> note;
  final double media;

  Situatie(this.elev, this.note)
      : assert(note.isNotEmpty),
        media = note.reduce((a, b) => a + b) / note.length {
    print('Am creat situația pentru $elev.');
  }
}

void main() {
  final s = Situatie('Ioana', [9, 10, 8]);
  print('${s.elev}: media ${s.media.toStringAsFixed(2)}');
}

Rezultat

Am creat situația pentru Ioana.
Ioana: media 9.00

Exemplul 3: Constructor const

Două expresii const cu aceleași valori dau același obiect, deci identical întoarce true. Fără const se creează obiecte separate.

class Culoare {
  final int r, g, b;
  const Culoare(this.r, this.g, this.b);
}

void main() {
  const rosu1 = Culoare(255, 0, 0);
  const rosu2 = Culoare(255, 0, 0);
  final rosu3 = Culoare(255, 0, 0);

  print(identical(rosu1, rosu2));
  print(identical(rosu1, rosu3));
}

Rezultat

true
false

Greșeli frecvente

  • Un câmp final atribuit în corpul constructorului ({ this.media = ...; }): eroare, câmpurile final se inițializează în parametri sau în lista de inițializare.
  • Folosirea lui this sau a metodelor obiectului în lista de inițializare: obiectul nu există încă.
  • Să crezi că poți avea doi constructori fără nume cu parametri diferiți: Dart nu are supraîncărcare. Folosește constructori numiți sau parametri opționali.

Comenzi înrudite

  • constructori numiți: Constructori cu nume propriu (Clasa.nume), pentru mai multe moduri de a crea același tip de obiect.
  • factory: Constructor care nu creează neapărat un obiect nou: poate întoarce unul din cache sau o subclasă.
  • this: Referință la obiectul curent, în interiorul metodelor și constructorilor unei clase.
  • class: Definește un tip nou de obiect, cu câmpuri (date) și metode (comportament).
  • const: Declară o constantă calculată la compilare; obiectele const sunt complet imuabile și partajate.