Records və pattern matching
Record — Dart 3-də gələn yüngül, anonim, immutable dəyər tipidir. Sinif elan etmədən bir neçə dəyəri bir yerdə qaytarmaq üçün istifadə olunur.
- Positional sahələr:
(int, String) row = (1, 'Ayan');— çıxışrow.$1,row.$2 - Named sahələr:
({int id, String name}) row = (id: 1, name: 'Ayan');— çıxışrow.id - Qarışıq:
(int, {String name})
Record-lar struktural bərabərliyə malikdir: (1, 'a') == (1, 'a') → true, əlavə ==/hashCode yazmağa ehtiyac yoxdur. Onlar həm də immutable-dır — sahəni dəyişmək mümkün deyil.
Nə vaxt record, nə vaxt sinif? Record — lokal, adsız, davranışsız məlumat üçün: funksiyanın iki dəyər qaytarması, Future.wait nəticələrinin qruplaşdırılması, fold içində aralıq akkumulyator. Sinif — domen anlayışı üçün: adı, validasiyası, metodları, sənədləşdirməsi olan tip. Public API-da record qaytarmaq adətən səhvdir, çünki sahə adları sənədləşdirmə rolunu tam oynamır və genişləndirmək çətindir.
Pattern matching record-ların digər yarısıdır. Pattern — dəyərin formasını yoxlayan və eyni anda hissələrini dəyişənlərə çıxaran konstruksiya.
Əsas yerlər:
- Destructuring elan:
final (id, name) = fetchRow();və yafinal (:id, :name) = row;(named sahələr üçün qısa forma) - `switch` ifadəsi (expression): dəyər qaytarır,
casesonundabreakyoxdur, budaqlar,ilə ayrılır - `switch` bəyanatı (statement): Dart 3-də
breakartıq tələb olunmur (fall-through yoxdur) - `if-case`:
if (json case {'id': final int id}) { ... }— tək bir formanı yoxlamaq üçün - Guard (`when`):
case Circle(:final r) when r > 10 =>— pattern uyğun gəldikdən sonra əlavə şərt
Pattern növləri: obyekt pattern-i (Circle(radius: final r)), record pattern-i ((final a, final b)), siyahı pattern-i ([final first, ...final rest]), map pattern-i ({'id': final id}), sabit pattern (0), wildcard (_), logical-or (1 || 2), cast (x as int), null-check (final x?).
| Konstruksiya | Nümunə | Nə vaxt |
|---|---|---|
| `switch` expression | `final label = switch (s) { Loading() => 'wait', _ => 'ok' };` | Dəyər hesablamaq |
| `switch` statement | `switch (s) { case Loading(): show(); }` | Yan effekt icra etmək |
| `if-case` | `if (json case {'id': final int id}) ...` | Yalnız bir forma maraqlandırır |
| Destructuring elan | `final (:width, :height) = size;` | Record və ya obyekti açmaq |
| Guard `when` | `case int n when n < 0 => 'negative',` | Formadan sonra əlavə şərt |
Exhaustiveness — mövzunun ən dəyərli hissəsi. sealed sinif iyerarxiyası üzərində switch yazanda compiler bütün alt tiplərin əhatə olunduğunu yoxlayır. Əgər sonradan yeni alt sinif əlavə etsən, hər əhatə olunmamış switch compile xətası verir — yəni redaktor sənə düzəldiləcək bütün yerləri göstərir.
Tipik forma belədir: sealed class Result {}, sonra final class Ok extends Result {...} və final class Err extends Result {...} — hər ikisi eyni faylda.
Burada default və ya _ budağı yazmaq exhaustiveness yoxlamasını söndürür — bu, ən çox edilən səhvdir. default yazsan, yeni alt sinif əlavə olunanda compiler susacaq və bug runtime-a keçəcək. Ona görə sealed iyerarxiyalarda default yazma.
sealed üç şeyi eyni anda verir: sinif abstrakt olur, eyni kitabxanadan kənarda extend/implement oluna bilmir, və compiler alt tiplərin tam siyahısını bilir. Alternativ modifikatorlar: final (extend olunmur), base (yalnız extend, implement yox), interface (yalnız implement).
Interview ipucu. "Record nə vaxt istifadə edərsən, nə vaxt sinif?" — bu, mühakimə sualıdır və hazır cavabı olmalıdır: "Record — lokal, adsız, davranışsız məlumat üçün (iki dəyər qaytarmaq, aralıq akkumulyator); sinif — adı, validasiyası və metodları olan domen anlayışı üçün. Public API-da record qaytarmıram."
İkinci sual demək olar ki, həmişə exhaustiveness-lə bağlı olur. Ən güclü cavab konkret ssenaridir: "`sealed` state iyerarxiyası + `switch` expression yazıram; yeni state əlavə edəndə compiler bütün əhatə olunmamış yerləri xəta kimi göstərir. `default` yazsam, bu qorunma itir — buna görə `sealed` üzərində `default` yazmıram." Bu cavab müsahibə "bu adam tip sistemini bug tapmaq üçün alət kimi işlədir" siqnalı verir.
📚 Mənbələr və sənədlər
- Recordsrəsmidart.dev
- Pattern-lərrəsmidart.dev