În proiectarea de sisteme robuste, utilizarea tipurilor primitive (cum ar fi int pentru identificatori de utilizatori, comenzi și produse) duce frecvent la bug-uri subtile: transmiterea accidentală a unui orderId în locul unui userId nu este semnalată de compilator dacă ambele sunt simple numere întregi.
Soluția clasică – crearea unei clase wrapper class UserId { final int value; ... } – aduce o penalizare severă de performanță: fiecare ID alocă un obiect nou pe heap, crește presiunea pe Garbage Collector și afectează randamentul în bucle critice.
Lansate ca facilitate stabilă în Dart 3.3, Extension Types (cunoscute și ca inline classes sau zero-cost abstractions) rezolvă această dilemă: oferă tipizare statică strictă la compilare, dar la execuție sunt complet eliminate, binarul executând codul cu tipul primitiv original, cu zero alocare de memorie suplimentară!
// Definirea a două tipuri distincte peste tipul primitiv int:
extension type const UserId(int id) {
// Putem adăuga metode și proprietăți calculate fără cost de instanțiere:
bool get isValid => id > 0;
void display() => print('ID Utilizator: $id');
}
extension type const OrderId(int id) {}
void cancelOrder(UserId user, OrderId order) {
print('Anulare comanda ${order.id} pentru utilizatorul ${user.id}');
}
void main() {
final user = UserId(1001);
final order = OrderId(5002);
// Apel valid tipizat:
cancelOrder(user, order);
// ❌ EROARE DE COMPILARE: Inversarea argumentelor este detectată imediat!
// cancelOrder(order, user);
// Error: The argument type 'OrderId' can't be assigned to the parameter type 'UserId'.
// La runtime, user și order sunt simple 'int' pe 64 de biți pe stivă!
}
Tabel Comparativ: Extension Type vs Extension Method vs Clasă Tradițională
| Caracteristică | Extension Type (Dart 3.3+) | Extension Methods (Dart 2.7+) | Clasă Wrapper Tradițională |
|---|---|---|---|
| Alocare pe Heap | 0 bytes (Zero-Cost) | 0 bytes | Da (Obiect complet pe heap) |
| Tip Nou la Compilare | Da (Incompatibil cu tipul de bază fără cast) | Nu (Tipul rămâne cel original) | Da |
| Ascunderea Interfeței Bazei | Da (Interfața originală nu este expusă implicit) | Nu (Toate metodele originale rămân accesibile) | Da |
| Interoperabilitate JS / Web | Nativă (folosit masiv în dart:js_interop) |
Limitată | Necesită serializare / wrapping |
// Folosind 'implements', putem alege să păstrăm metodele tipului de bază:
extension type SafeString(String _raw) implements String {
// Datorită 'implements String', avem acces direct la .length, .contains etc.,
// dar putem suprascrie sau adăuga validări personalizate:
bool get isSanitized => !contains('<script>');
}
void main() {
final text = SafeString('Salutare lume');
print(text.length); // 13 (din interfața String)
print(text.isSanitized); // true
}