Enum: Pilihan Terbatas
Merepresentasikan pilihan tetap dengan aman: enum, switch exhaustive, enhanced enum.
Pilihan yang tidak boleh salah ketik
Status pesanan hanya boleh: menunggu, diproses, dikirim, selesai. Kalau direpresentasikan sebagai String bebas, typo 'selsai' lolos tanpa error dan merusak logika. Enum membatasi nilai pada pilihan yang sudah ditentukan, diperiksa compiler.
Analogi: enum itu seperti soal pilihan ganda. Kamu tidak menulis jawaban bebas (rawan salah), kamu melingkari A/B/C/D yang sudah disediakan.
Kenapa enum ada?
Tiga alasan: type safety (nilai salah ditolak compile-time), exhaustiveness (switch wajib menangani semua kasus), dan dokumentasi (daftar nilai valid terlihat langsung di kode).
Enum dasar
enum StatusPesanan { menunggu, diproses, dikirim, selesai }
void main() {
var status = StatusPesanan.diproses;
print(status); // StatusPesanan.diproses
print(status.name); // 'diproses', nama sebagai string
print(status.index); // 1, posisi urutan
// Semua nilai
print(StatusPesanan.values); // [menunggu, diproses, dikirim, selesai]
}Setiap nilai enum adalah objek tunggal (singleton). Perbandingan memakai == biasa dan dijamin benar.
Contoh kedua, enum + switch exhaustive:
enum Hari { senin, selasa, rabu, kamis, jumat, sabtu, minggu }
String kegiatan(Hari h) {
switch (h) {
case Hari.senin:
case Hari.selasa:
case Hari.rabu:
case Hari.kamis:
case Hari.jumat:
return 'Kerja';
case Hari.sabtu:
case Hari.minggu:
return 'Libur';
}
}
void main() {
print(kegiatan(Hari.sabtu)); // Libur
print(kegiatan(Hari.rabu)); // Kerja
}Karena semua nilai tercakup, switch tidak butuh default. Kalau nanti enum tambah nilai baru, compiler langsung protes: "kasus belum ditangani!" Ini jaring pengaman yang luar biasa.
Enhanced enum: enum dengan data
Enum modern bisa membawa field dan method:
enum Level {
mudah('Gampang banget', 1),
sedang('Lumayan', 2),
sulit('Keringat dingin', 3);
const Level(this.label, this.bobot);
final String label;
final int bobot;
bool get berat => bobot >= 3;
}
void main() {
var l = Level.sedang;
print('${l.label} (bobot ${l.bobot})'); // Lumayan (bobot 2)
print(Level.sulit.berat); // true
for (var level in Level.values) {
print('${level.name}: ${level.label}');
}
}Enhanced enum menggantikan pola "class dengan konstanta statis" yang bertele-tele. Constructor enum wajib const.
Kesalahan umum
1. Memakai String untuk pilihan tetap
// Rapuh: typo lolos
void proses(String status) {
if (status == 'selsai') {} // typo, tidak ada yang protes
}// BENAR
void proses(StatusPesanan status) {
if (status == StatusPesanan.selesai) {}
// proses('selsai'); // ERROR compile
}2. Membandingkan enum dengan string
void main() {
var s = StatusPesanan.diproses;
// print(s == 'diproses'); // false! beda tipe
print(s == StatusPesanan.diproses); // true
print(s.name == 'diproses'); // true, kalau memang butuh string
}3. Mengandalkan index untuk logika bisnis
index bisa berubah jika urutan enum diubah. Untuk data persisten (database), simpan name, bukan index.
Kesimpulan
Enum = pilihan terbatas yang aman, diperiksa compiler, bersahabat dengan switch exhaustive. Enhanced enum menambah field/method. Gantikan String bebas untuk status, kategori, dan mode dengan enum.
Catatan teknis: Nilai enum adalah konstanta compile-time, sehingga bisa dipakai di
caseswitch, anotasi, dan nilai default parameter.
Tantangan
Lampu lalu lintas
Buat enum Lampu {merah, kuning, hijau} dengan enhanced enum berisi durasi (detik) dan method aksi() yang mengembalikan 'Berhenti'/'Siap-siap'/'Jalan'. Cetak semua nilai dengan aksinya.
enum Lampu {
// TODO: merah(30), kuning(5), hijau(25) + field durasi + method aksi()
}
void main() {
// TODO: loop Lampu.values, cetak nama, durasi, aksi
}