Enhanced enum-lar
Dart 2.17-yə qədər enum sadəcə adlar siyahısı idi. İndi enum tam hüquqlu tipdir: sahələri, const konstruktoru, metodları, getter-ləri ola bilər, interfeys implement edə və mixin qoşa bilər.
Qaydalar:
- Dəyərlər birinci yazılır, sonra
;qoyulur, sonra qalan üzvlər gəlir. - Konstruktor mütləq
constolmalıdır və bütün sahələrfinal— çünki enum dəyərləri compile-time sabitləridir. - Enum başqa class-ı
extendsedə bilməz (implicit olaraqEnum-dan gəlir), ammaimplementsvəwithmümkündür. - Ən azı bir dəyər olmalıdır — boş enum yoxdur.
Bu, praktikada nə deməkdir: əvvəllər switch-lə yazılan "enum → dəyər" xəritələri (kod, rəng, mətn açarı) artıq birbaşa enum-un içində sahə kimi yaşayır.
| Üzv | Nə qaytarır | Diqqət |
|---|---|---|
| `Role.values` | Bütün dəyərlərin `List` şəklində siyahısı, elan sırasında | Dəyişməz siyahıdır; `where`, `map` ilə sərbəst işlətmək olar |
| `role.name` | Dəyərin adı `String` kimi — `'admin'` | `toString()` isə `'Role.admin'` verir — serializasiyada `name` istifadə et |
| `role.index` | 0-dan başlayan sıra nömrəsi | Bazaya yazma! Dəyərlərin sırası dəyişəndə köhnə data korlanır |
| `Role.values.byName('admin')` | Ada görə dəyəri tapır | Tapılmasa **ArgumentError atır** — xarici datanı birbaşa vermə |
| `Role.values.asNameMap()` | `Map<String, Role>` — təhlükəsiz axtarış üçün | `asNameMap()[raw]` `null` qaytarır, atmır |
| `compareTo` | Default olaraq `index`-ə görə müqayisə (`Enum` `Comparable` deyil, amma `EnumX` genişləndirmələri var) | Məntiqi sıralama lazımdırsa `Comparable` implement et |
Enum üzərində exhaustive switch. Enum-un dəyər çoxluğu bağlıdır, ona görə kompilyator switch-i tam yoxlayır: bütün dəyərləri əhatə etsən default lazım deyil. Yeni dəyər əlavə edən kimi default-suz switch-lər kompilyasiya olunmur — bu, sealed class ilə eyni faydadır və enum-un ən güclü tərəfidir.
Buna görə praktik qayda: enum üzərində `default` yazma. default exhaustiveness yoxlamasını söndürür və "yeni statusu emal etməyi unutduq" bug-u səssizcə runtime-a keçir.
switch ifadəsi (expression) formasını üstün tut — o, dəyər qaytarır və hər şaxənin nəyisə qaytarmasını məcbur edir:
String label(Role r) => switch (r) { Role.admin => 'Admin', ... };
Enum, yoxsa sealed class? Bu, artıq standart müsahibə sualıdır. Fərqi bir cümləyə yığmaq olar: enum sabit dəyərlər çoxluğudur, sealed hierarchy isə fərqli formalı variantlar çoxluğudur.
Seçim meyarları:
- Hər variantın öz datası varmı?
CardPayment(last4)vəCashPayment()fərqli sahələr daşıyır → sealed. Enum-da bütün dəyərlər eyni sahə dəstini paylaşır. - Variant sayı runtime-da genişlənməlidirmi? İkisi də yox — hər ikisi bağlıdır.
- Sadəcə adlar siyahısıdırsa (
Role,Direction,LogLevel) → enum. Daha sadə,valuespulsuz gəlir, serializasiya asandır. - Hər variant üçün fərqli davranış lazımdırsa, hər ikisi işləyir: enum-da metod, sealed-də override.
Əlavə praktik arqument: enum values, byName və index ilə hazır serializasiya verir; sealed hierarchy üçün bunu özün yazmalısan. Əvəzində sealed generic ola bilir (Result<T>) və enum ola bilmir.
Müsahibə ipucu. İki tələ var, ikisi də praktikadan gəlir.
Birincisi: "enum dəyərini bazaya necə yazarsan?" Zəif cavab index-dir. Güclü cavab: `index` heç vaxt persist edilmir — kimsə dəyərləri əlifba sırası ilə düzəldən kimi bütün köhnə data səhv oxunur. name (və ya enum-un içindəki açıq code sahəsi) yazılır və oxuyanda asNameMap() ilə təhlükəsiz parse edilir.
İkincisi: "`byName` ilə server datasını parse etmək olar?" — Xeyr, byName tapmayanda ArgumentError atır. Doğru yanaşma Role.values.asNameMap()[raw] ?? Role.unknown və ya firstWhere(..., orElse: ...) — və enum-a qəsdən unknown dəyəri əlavə etmək. Bu cavab səni "dili bilən"dən "prod-da işləyən" səviyyəyə keçirir.
📚 Mənbələr və sənədlər
- Enum tiplərirəsmidart.dev