dartenumMenengah4 mnt baca

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

dart
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:

dart
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:

dart
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

dart
// Rapuh: typo lolos
void proses(String status) {
  if (status == 'selsai') {} // typo, tidak ada yang protes
}
dart
// BENAR
void proses(StatusPesanan status) {
  if (status == StatusPesanan.selesai) {}
  // proses('selsai'); // ERROR compile
}

2. Membandingkan enum dengan string

dart
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 case switch, 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.

text
enum Lampu {
  // TODO: merah(30), kuning(5), hijau(25) + field durasi + method aksi()
}

void main() {
  // TODO: loop Lampu.values, cetak nama, durasi, aksi
}