Record, Pattern Matching & Sealed Class
Fitur khas Dart 3: record untuk mengembalikan banyak nilai, destructuring, pattern matching di switch/if-case, dan sealed class dengan pengecekan lengkap.
Dart 3 membawa fitur baru
Dart 3 menambahkan tiga fitur yang membuat kode jauh lebih ringkas dan aman: record, pattern, dan sealed class. Ketiganya sering dipakai bersama.
Record: kumpulan nilai ringan
Kadang function perlu mengembalikan lebih dari satu nilai. Tanpa record, kamu harus membuat class atau memakai List/Map yang kehilangan tipe. Record adalah jawabannya:
(String, int) orang = ('Budi', 25);
print(orang.$1); // Budi (field posisi: $1, $2, ...)
print(orang.$2); // 25
({String nama, int umur}) siswa = (nama: 'Ani', umur: 17);
print(siswa.nama); // Ani (field bernama)
// Mengembalikan banyak nilai
(int min, int max) rentang(List<int> data) {
var urut = [...data]..sort();
return (urut.first, urut.last);
}
var (kecil, besar) = rentang([5, 2, 9]); // destructuring
print('$kecil sampai $besar'); // 2 sampai 9
Record bersifat immutable dan punya == otomatis berdasarkan isi: (1, 2) == (1, 2) adalah true. Cocok untuk data kecil sementara; untuk data besar atau yang punya perilaku, tetap pakai class.
Pattern: mencocokkan bentuk data
Pattern memeriksa bentuk sebuah nilai sekaligus mengambil bagian-bagiannya.
// Destructuring List dan Map
var [a, b, ...sisa] = [1, 2, 3, 4, 5]; // a=1, b=2, sisa=[3,4,5]
var {'nama': nama, 'umur': umur} = {'nama': 'Budi', 'umur': 25};
// Menukar nilai tanpa variabel bantu
var (x, y) = (1, 2);
(x, y) = (y, x);
// Pengecekan di if-case
Object nilai = 42;
if (nilai case int n when n > 10) {
print('Angka besar: $n');
}
switch dengan pattern
String deskripsi(Object o) => switch (o) {
0 => 'nol',
int n when n < 0 => 'negatif',
int n => 'angka $n',
String s when s.isEmpty => 'teks kosong',
String s => 'teks "$s"',
[var a, var b] => 'list dua elemen: $a, $b',
(int x, int y) => 'titik ($x, $y)',
_ => 'tidak dikenal',
};
Setiap cabang menggabungkan pola (bentuk/tipe) dengan guard opsional when. Cabang diperiksa dari atas ke bawah; yang pertama cocok dijalankan.
Sealed class: himpunan subtipe tertutup
sealed menyatakan bahwa semua subtipe class ini didefinisikan di berkas yang sama. Compiler jadi tahu semua kemungkinan, dan memaksa switch menangani semuanya:
sealed class Bentuk {}
class Lingkaran extends Bentuk {
final double r;
Lingkaran(this.r);
}
class Persegi extends Bentuk {
final double sisi;
Persegi(this.sisi);
}
class Segitiga extends Bentuk {
final double alas, tinggi;
Segitiga(this.alas, this.tinggi);
}
double luas(Bentuk b) => switch (b) {
Lingkaran(r: var r) => 3.14159 * r * r,
Persegi(sisi: var s) => s * s,
Segitiga(alas: var a, tinggi: var t) => a * t / 2,
}; // tanpa default. Menambah subtipe baru tapi lupa menangani => error compile
Pola Lingkaran(r: var r) adalah object pattern: mencocokkan tipe lalu mengambil property-nya.
Contoh nyata: status pemuatan data
sealed class Keadaan {}
class Memuat extends Keadaan {}
class Berhasil extends Keadaan {
final List<String> data;
Berhasil(this.data);
}
class Gagal extends Keadaan {
final String pesan;
Gagal(this.pesan);
}
String tampilkan(Keadaan k) => switch (k) {
Memuat() => 'Memuat...',
Berhasil(data: var d) => 'Ada ${d.length} data',
Gagal(pesan: var p) => 'Error: $p',
};
Pola ini adalah dasar manajemen state yang rapi di aplikasi Flutter.
Ringkasan
| Fitur | Gunanya |
|---|---|
| Record | Menggabung/mengembalikan beberapa nilai tanpa class |
| Destructuring | Membongkar record/list/map ke variabel |
Pattern + when | Percabangan yang memeriksa bentuk data |
| Sealed class | Subtipe tertutup, switch wajib lengkap |
Error umum
The type 'Bentuk' is not exhaustively matched by the switch cases→ ada subtipe sealed yang belum ditangani.The record field '$3' isn't defined→ indeks field record salah (mulai dari$1).- Pattern tidak cocok pada destructuring list → jumlah elemen berbeda, lemparan
StateError.