Ce face implements
În Dart orice clasă definește implicit și o interfață: lista membrilor ei publici. class Cerc implements Forma spune că Cerc poate fi folosit ca Forma, dar, spre deosebire de extends, nu primește nimic: trebuie să scrie el toate metodele, getter-ele și câmpurile lui Forma.
O clasă poate implementa mai multe interfețe deodată (implements Comparable<Nota>, Exportabil) și poate în același timp să extindă o clasă. De obicei interfețele sunt clase abstract sau abstract interface.
implements este util pentru a înlocui o componentă cu alta (de exemplu o bază de date reală cu una de test) fără să schimbi codul care o folosește.
Exemple
Exemplul 1: Două implementări ale aceleiași interfețe
Funcția trimite nu știe dacă primește e-mail sau SMS; știe doar că poate apela notifica. SMS-ul scurtează mesajul la primele 20 de caractere.
abstract class Notificator {
void notifica(String destinatar, String mesaj);
}
class Email implements Notificator {
@override
void notifica(String destinatar, String mesaj) =>
print('E-mail către $destinatar: $mesaj');
}
class Sms implements Notificator {
@override
void notifica(String destinatar, String mesaj) =>
print('SMS către $destinatar: ${mesaj.substring(0, 20)}...');
}
void trimite(Notificator n) => n.notifica('Ana', 'Comanda ta a fost livrată în Cluj.');
void main() {
trimite(Email());
trimite(Sms());
}
Rezultat
E-mail către Ana: Comanda ta a fost livrată în Cluj.
SMS către Ana: Comanda ta a fost li...
Exemplul 2: Mai multe interfețe deodată
Nota implementează Comparable (pentru sortare) și o interfață proprie.
abstract class Exportabil {
String inCsv();
}
class Nota implements Comparable<Nota>, Exportabil {
final String elev;
final int valoare;
Nota(this.elev, this.valoare);
@override
int compareTo(Nota alta) => alta.valoare.compareTo(valoare);
@override
String inCsv() => '$elev;$valoare';
}
void main() {
final note = [Nota('Ana', 8), Nota('Bogdan', 10), Nota('Carla', 9)]..sort();
for (final n in note) {
print(n.inCsv());
}
}
Rezultat
Bogdan;10
Carla;9
Ana;8
Exemplul 3: Implementarea unei clase obișnuite pentru teste
MeteoFals implementează interfața lui Meteo și înlocuiește serviciul real, fără să moștenească nimic din el.
class Meteo {
double temperatura(String oras) {
throw UnimplementedError('aici s-ar face o cerere pe internet');
}
}
class MeteoFals implements Meteo {
@override
double temperatura(String oras) => {'Iași': 18.5, 'Constanța': 24.0}[oras] ?? 20;
}
String sfat(Meteo m, String oras) =>
m.temperatura(oras) > 22 ? '$oras: ia ochelari de soare' : '$oras: ia o geacă';
void main() {
final meteo = MeteoFals();
print(sfat(meteo, 'Iași'));
print(sfat(meteo, 'Constanța'));
}
Rezultat
Iași: ia o geacă
Constanța: ia ochelari de soare
Greșeli frecvente
- Să crezi că
implementsmoștenește codul: trebuie să scrii fiecare membru, altfel apareMissing concrete implementation of .... - Uitarea câmpurilor: un câmp public al interfeței trebuie implementat și el (ca un câmp sau ca getter/setter).
- Să implementezi o clasă
basesaufinaldin alt fișier: modificatorii de clasă interzic asta.
Comenzi înrudite
extends: Creează o subclasă care moștenește câmpurile și metodele altei clase și le poate înlocui.abstract: O clasă abstractă nu poate fi instanțiată direct; definește ce trebuie să facă subclasele ei.interface: Modificator de clasă (Dart 3): în afara fișierului ei, clasa poate fi doar implementată, nu și extinsă.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.