Ce face mixin și with
Un mixin grupează cod reutilizabil (metode, getter-e, câmpuri) care nu are sens singur. Cu with îl „amesteci” într-o clasă: class Rata extends Pasare with Inotator, Zburator. Clasa primește tot codul mixin-urilor, ca și cum l-ar fi scris ea.
Spre deosebire de extends, poți folosi oricâte mixin-uri. Ele se aplică în ordine, de la stânga la dreapta; dacă două au aceeași metodă, câștigă ultimul. Un mixin nu are constructori și nu se poate crea singur (Inotator() este o eroare).
Cu mixin Nume on Baza mixin-ul poate fi folosit doar în subclase ale lui Baza și, în schimb, poate apela metodele lui Baza (inclusiv cu super). Din Dart 3, mixin class declară ceva ce poate fi folosit și ca clasă obișnuită, și ca mixin.
Exemple
Exemplul 1: Abilități combinate
Rața primește ambele abilități, pinguinul doar înotul.
mixin Inotator {
void inoata() => print('$runtimeType înoată.');
}
mixin Zburator {
void zboara() => print('$runtimeType zboară.');
}
class Pasare {}
class Rata extends Pasare with Inotator, Zburator {}
class Pinguin extends Pasare with Inotator {}
void main() {
final rata = Rata();
rata.inoata();
rata.zboara();
Pinguin().inoata();
final List<Pasare> pasari = [rata, Pinguin()];
for (final p in pasari) {
print('${p.runtimeType} zboară? ${p is Zburator}');
}
}
Rezultat
Rata înoată.
Rata zboară.
Pinguin înoată.
Rata zboară? true
Pinguin zboară? false
Exemplul 2: Mixin cu stare și restricție on
Jurnalizat poate fi folosit doar pe subclase ale lui Serviciu și apelează super.porneste().
class Serviciu {
final String nume;
Serviciu(this.nume);
void porneste() => print('$nume a pornit.');
}
mixin Jurnalizat on Serviciu {
final List<String> jurnal = [];
@override
void porneste() {
jurnal.add('pornire $nume');
super.porneste();
}
}
class ServiciuPlati extends Serviciu with Jurnalizat {
ServiciuPlati() : super('Plăți');
}
void main() {
final s = ServiciuPlati();
s.porneste();
s.porneste();
print(s.jurnal);
}
Rezultat
Plăți a pornit.
Plăți a pornit.
[pornire Plăți, pornire Plăți]
Exemplul 3: Ordinea mixin-urilor
Ambele mixin-uri au salut; fiecare cheamă super.salut(), deci se vede ordinea în care au fost aplicate.
class Baza {
String salut() => 'Bază';
}
mixin A on Baza {
@override
String salut() => 'A > ${super.salut()}';
}
mixin B on Baza {
@override
String salut() => 'B > ${super.salut()}';
}
class AB extends Baza with A, B {}
class BA extends Baza with B, A {}
void main() {
print(AB().salut());
print(BA().salut());
}
Rezultat
B > A > Bază
A > B > Bază
Greșeli frecvente
class Pasare extends ZburatorcândZburatoreste unmixin: eroareaClasses can only extend other classes. Foloseștewith.- Constructori într-un
mixin: nu sunt permiși. Inițializează câmpurile direct sau foloseștelate. - Din Dart 3, o clasă obișnuită nu mai poate fi folosită ca mixin; dacă vrei ambele roluri, declar-o
mixin class.
Comenzi înrudite
extends: Creează o subclasă care moștenește câmpurile și metodele altei clase și le poate înlocui.implements: O clasă promite că are toți membrii altor clase (interfețe) și îi scrie singură, fără să moștenească codul lor.super: Accesează clasa părinte: constructorul ei (în lista de inițializare) sau metodele pe care subclasa le-a înlocuit.abstract: O clasă abstractă nu poate fi instanțiată direct; definește ce trebuie să facă subclasele ei.