Capitol gratuit

Limbajul Dart - esențial

Dart este limbajul de programare pe care se bazează Flutter. Este un limbaj cu tipare statică opțională, compilat nativ (AOT - Ahead Of Time pentru producț...

Introducere

Dart este limbajul de programare pe care se bazează Flutter. Este un limbaj cu tipare statică opțională, compilat nativ (AOT - Ahead Of Time pentru producție, JIT - Just In Time pentru dezvoltare, ceea ce face posibil Hot Reload-ul). Sintaxa este familiară oricui a lucrat cu Java, C#, JavaScript sau Kotlin.

Variabile și tipuri de date

// Tip explicit
String nume = 'Andrei';
int varsta = 28;
double pret = 149.99;
bool esteActiv = true;

// Inferență de tip cu var
var oras = 'București'; // Dart deduce automat: String

// Constante
final DateTime dataCreare = DateTime.now(); // se calculează o dată, la runtime
const double tvaProcent = 19.0;             // valoare fixă, la compilare

// Tip dinamic (evitați dacă se poate)
dynamic oricare = 'text';
oricare = 42; // permis, dar pierdeți siguranța de tip

Null safety

Din Dart 3, null safety este obligatorie în orice proiect nou. O variabilă nu poate fi null decât dacă tipul ei este marcat explicit cu ?.

String numeObligatoriu = 'Maria';   // nu poate fi null niciodată
String? numeOptional;               // poate fi null

// Operatorul ?? oferă o valoare implicită dacă expresia e null
String afisare = numeOptional ?? 'Fără nume';

// Operatorul ?. apelează metoda doar dacă obiectul nu e null
int? lungime = numeOptional?.length;

// Operatorul ! (bang) - "sunt sigur că nu e null" (folosiți cu grijă!)
String numeSigur = numeOptional!;

// Atribuire condiționată
numeOptional ??= 'Valoare implicită';
Atenție: Operatorul ! aruncă o excepție la runtime dacă valoarea este de fapt null. Folosiți-l doar când sunteți absolut sigur, sau preferați verificări explicite cu if (variabila != null).

Funcții

// Funcție simplă
int aduna(int a, int b) {
return a + b;
}

// Sintaxă arrow pentru funcții cu o singură expresie
int inmulteste(int a, int b) => a * b;

// Parametri opționali cu valoare implicită (named parameters)
void salutare({String nume = 'Vizitator', bool formal = false}) {
print(formal ? 'Bună ziua, $nume!' : 'Salut, $nume!');
}
salutare(nume: 'Ioana', formal: true);

// Parametri obligatorii denumiți
void creeazaUtilizator({required String email, required String parola}) {
// ...
}

// Funcții ca parametri (higher-order functions)
void proceseaza(List numere, int Function(int) transformare) {
for (var n in numere) {
print(transformare(n));
}
}
proceseaza([1, 2, 3], (n) => n * n);

Clase și obiecte

class Produs {
final String nume;
final double pret;
bool inStoc;

// Constructor
Produs({required this.nume, required this.pret, this.inStoc = true});

// Constructor numit
Produs.faraStoc(this.nume, this.pret) : inStoc = false;

// Metodă
String descriere() {
return '$nume - ${pret.toStringAsFixed(2)} lei';
}

// Getter calculat
String get status => inStoc ? 'Disponibil' : 'Stoc epuizat';
}

// Moștenire
class ProdusReducere extends Produs {
final double procentReducere;

ProdusReducere({
required super.nume,
required super.pret,
required this.procentReducere,
});

double get pretFinal => pret * (1 - procentReducere / 100);
}

void main() {
final produs = Produs(nume: 'Cască wireless', pret: 249.99);
print(produs.descriere());
print(produs.status);
}

Colecții (List, Map, Set)

// List - listă ordonată
List orase = ['București', 'Cluj-Napoca', 'Iași'];
orase.add('Timișoara');
final primulOras = orase.first;

// Map - perechi cheie-valoare
Map stocProduse = {
'telefon': 12,
'laptop': 5,
};
stocProduse['tabletă'] = 8;

// Set - elemente unice, fără duplicate
Set categorii = {'electronice', 'mobilier', 'electronice'};
print(categorii.length); // 2, duplicatul e eliminat automat

// Operații funcționale utile
final numereMari = [1, 5, 12, 3, 20]
.where((n) => n > 4)
.map((n) => n * 2)
.toList();
// rezultat: [10, 24, 40]

Programare asincronă - Future, async/await, Stream

Operațiile care durează (cereri de rețea, citire fișiere, baze de date) sunt asincrone în Dart, prin tipul Future.

Future descarcaDate() async {
await Future.delayed(const Duration(seconds: 2)); // simulează o cerere
return 'Date primite de la server';
}

void afiseazaDate() async {
print('Se încarcă...');
final rezultat = await descarcaDate();
print(rezultat);
}

// Gestionarea erorilor cu try/catch
Future incarcaSigur() async {
try {
final date = await descarcaDate();
print(date);
} catch (eroare) {
print('A apărut o eroare: $eroare');
} finally {
print('Operațiune finalizată');
}
}

// Stream - un flux de valori care sosesc în timp (ex: actualizări live)
Stream numaraSecunde() async* {
for (int i = 1; i <= 5; i++) {
await Future.delayed(const Duration(seconds: 1));
yield i;
}
}

void ascultaStream() {
numaraSecunde().listen((valoare) {
print('Secunda: $valoare');
});
}

Operatori utili specifici Dart

OperatorRolExemplu
??Valoare implicită dacă e nullnume ?? 'Anonim'
?.Apel sigur pe obiect posibil nullutilizator?.email
??=Atribuie doar dacă e nulltotal ??= 0
.. (cascade)Apeluri multiple pe același obiectlista..add(1)..add(2)
is / asVerificare / conversie de tipif (obiect is String)
... (spread)Extinde o colecție în alta[...lista1, ...lista2]
Sfat: Dacă veniți din JavaScript, TypeScript sau Kotlin, majoritatea conceptelor Dart vă vor părea familiare. Cea mai mare diferență de mentalitate este obligativitatea null safety, care previne o clasă întreagă de erori la runtime încă din faza de scriere a codului.

Continuați cu restul cursului

Acesta este capitolul 3 din cele 14 ale cursului, cu 8 lecții din 85. Cumpărați cursul și parcurgeți tot conținutul în cont, cu progres salvat, test final și certificat.

Cumpărați cursul la 130 €