latenull-safetyinisialisasiMahir5 mnt baca

Keyword late

Menunda inisialisasi dengan late: kapan berguna dan jebakan LateInitializationError.

Masalah yang diselesaikan late

Null safety menuntut variabel non-nullable langsung terisi. Tapi ada kasus wajar di mana nilainya belum tersedia saat deklarasi:

dart
class Game {
  late String pemain; // belum tahu siapa pemainnya saat object dibuat

  void mulai(String nama) {
    pemain = nama;
  }

  void tampil() {
    print('Pemain: $pemain');
  }
}

void main() {
  var g = Game();
  g.mulai('Rizky');
  g.tampil();
}

Tanpa late, pemain harus nullable (String?) atau diisi di constructor. Dengan late, kita bilang ke compiler: "tenang, saya yang tanggung jawab mengisinya sebelum dipakai".

LateInitializationError: janji yang ingkar

Kalau kamu lupa menepati janji, Dart menghukummu saat runtime:

dart
late String data;

void main() {
  print(data); // LateInitializationError: Field 'data' has not been initialized.
}

Error ini tidak tertangkap saat compile, hanya muncul saat program jalan dan baris itu dieksekusi. Makanya late dikategorikan topik mahir: butuh disiplin.

Catatan teknis: LateInitializationError adalah salah satu error paling membingungkan buat pemula karena pesannya teknis dan munculnya tidak tentu. Kalau kamu melihatnya, artinya ada variabel late yang dibaca sebelum diisi. Telusuri alur program: pastikan setiap jalur eksekusi mengisi variabel itu dulu sebelum ada yang membacanya.

late final: isi sekali, tapi nanti

Kombinasi late final untuk nilai yang dihitung sekali secara malas:

dart
class Config {
  late final String token = _ambilToken();

  String _ambilToken() {
    print('Mengambil token...');
    return 'abc123';
  }
}

void main() {
  var c = Config();
  print('Object dibuat');
  print(c.token); // 'Mengambil token...' baru dicetak DI SINI
  print(c.token); // tidak dihitung ulang
}

Fungsi _ambilToken() baru dipanggil saat token pertama kali dibaca, bukan saat object dibuat. Ini disebut lazy initialization: hemat kalau perhitungannya mahal dan belum tentu dibutuhkan.

Kapan pakai late (dan kapan tidak)

Cocok untuk late:

  • Field yang diisi di initState() pada Flutter (pola sangat umum)
  • Nilai mahal yang dihitung malas dengan late final
  • Variabel top-level yang butuh setup dulu

Jangan pakai late kalau:

  • Nilainya bisa diisi langsung (pakai final biasa)
  • Bisa jadi tidak terisi (pakai nullable ? saja, lebih jujur)
  • Kamu tidak yakin alur pengisiannya (risiko LateInitializationError)
dart
// Kurang baik: late + nullable = membingungkan, hindari
// late String? nama;

// Baik: jujur nullable
String? nama;

// Baik: late dengan alur jelas
late final String id;
void setup() {
  id = 'user-123';
}

Pola Flutter: late di State

Ini pola yang akan sering kamu lihat di Flutter:

dart
// Ilustrasi pola (bukan kode Flutter asli):
class HalamanState {
  late String judul;

  void initState() {
    judul = 'Beranda'; // diisi sekali saat inisialisasi
  }

  void build() {
    print(judul); // aman dibaca setelah initState
  }
}

Framework menjamin initState() jalan sebelum build(), jadi late di sini aman. Tapi kalau kamu baca judul sebelum initState, tetap error. Pahami kontrak urutan eksekusi setiap kali pakai late.

Kesimpulan

late adalah alat tajam: menyelesaikan masalah inisialisasi tertunda dengan elegan, tapi menuntut kamu paham alur program. Kalau ragu, pilih nullable (?) yang jujur daripada late yang berisiko. Kode yang sedikit lebih verbose tapi tidak pernah crash selalu menang.