dartnull-safetyoperatorMahir4 mnt baca

Operator Nullable: ?., ??, ??=

Operator sakti untuk bekerja dengan nilai nullable tanpa if bertingkat.

Operator-operator penyelamat null

Menangani null dengan if di mana-mana membuat kode kembung. Dart menyediakan operator khusus yang ringkas: ?. (panggil hanya jika tidak null), ?? (default jika null), dan ??= (isi hanya jika masih null).

Analogi: operator ini seperti asisten yang mengecek "apakah kotaknya kosong?" sebelum bertindak, sehingga kamu tidak perlu menulis pengecekan manual berulang-ulang.

Kenapa operator ini ada?

Karena pola "cek null lalu pakai" muncul di mana-mana: konfigurasi opsional, data API yang mungkin hilang, preferensi pengguna. Tanpa operator khusus, 30% kodemu hanya berisi if (x != null).

?. : null-aware access

dart
void main() {
  String? nama;

  // Tanpa ?.: harus cek manual
  int panjang1 = nama == null ? 0 : nama.length;

  // Dengan ?.: satu baris
  int? panjang2 = nama?.length; // null, tidak crash
  print(panjang1); // 0
  print(panjang2); // null

  nama = 'Budi';
  print(nama?.length); // 4, normal saat tidak null
}

nama?.length artinya "jika nama tidak null, ambil length-nya; jika null, hasilnya null". Rantai panjang juga bisa:

dart
class Pengguna {
  String? nama;
  Pengguna([this.nama]);
}

class Pesanan {
  Pengguna? pembeli;
  Pesanan([this.pembeli]);
}

void main() {
  Pesanan p1 = Pesanan();
  // Tanpa ?.: mimpi buruk bersarang
  print(p1.pembeli?.nama?.length); // null, aman!

  Pesanan p2 = Pesanan(Pengguna('Budi'));
  print(p2.pembeli?.nama?.length); // 4
}

Satu baris menggantikan tiga level if bersarang. Inilah operator null safety yang paling sering dipakai.

?? : nilai default

dart
void main() {
  String? namaPanggilan;

  // Jika null, pakai 'Kawan'
  String sapa = namaPanggilan ?? 'Kawan';
  print('Halo, $sapa!'); // Halo, Kawan!

  namaPanggilan = 'Bang Jago';
  print('Halo, ${namaPanggilan ?? 'Kawan'}!'); // Halo, Bang Jago!
}

a ?? b = "pakai a, kecuali a null, maka pakai b". Kombinasi maut dengan ?.:

dart
void main() {
  Map<String, String> kamus = {'apel': 'apple'};

  // Akses map + default dalam satu baris
  print(kamus['apel'] ?? 'tidak ada');   // apple
  print(kamus['durian'] ?? 'tidak ada'); // tidak ada

  String? input;
  int panjang = input?.length ?? 0; // pola klasik: aman + default
  print(panjang); // 0
}

??= : isi jika masih null

dart
void main() {
  String? tema;
  tema ??= 'terang'; // tema masih null, jadi diisi
  print(tema); // terang

  tema ??= 'gelap'; // tema sudah ada isi, TIDAK ditimpa
  print(tema); // tetap terang

  // Ekuivalen panjangnya:
  // if (tema == null) tema = 'terang';
}

Berguna untuk inisialisasi malas (lazy init) dan nilai default yang hanya dihitung jika dibutuhkan.

Kesalahan umum

1. ?. lalu kaget hasilnya nullable

dart
void main() {
  String? nama = 'Budi';
  int? panjang = nama?.length; // int?, BUKAN int!
  // int p2 = nama?.length; // ERROR: int? tidak bisa ke int
  int p3 = nama?.length ?? 0; // BENAR
  print(p3);
}

Hasil ?. selalu nullable. Pasangkan dengan ?? untuk mendapatkan non-nullable.

2. ?? dengan tipe tidak cocok

dart
// SALAH
void main() {
  int? n;
  // String s = n ?? 'nol'; // ERROR: int? ?? String
}
dart
// BENAR: default harus tipe yang kompatibel
void main() {
  int? n;
  int m = n ?? 0;
  print(m);
}

3. Berlebihan memakai ?.

dart
// Tidak perlu: nama sudah non-nullable
void main() {
  String nama = 'Budi';
  // print(nama?.length); // warning: tidak perlu ?.
  print(nama.length); // cukup ini
}

?. hanya untuk nullable. Memakainya pada non-nullable memicu warning dan menandakan kamu tidak yakin dengan tipemu sendiri.

Kesimpulan

?. untuk akses aman berantai, ?? untuk nilai default, ??= untuk isi-jika-kosong. Tiga operator ini menghapus sebagian besar if null manual dan membuat kode null-safe tetap ringkas dibaca.

Catatan teknis: a ?? b hanya mengevaluasi b jika a null (lazy evaluation). Jadi config ?? hitungDefaultMahal() aman: fungsi mahal tidak dipanggil jika config sudah ada.

Tantangan

Profil dengan default

Buat fungsi tampilkanProfil({String? nama, int? umur}) yang mencetak nama (default "Anonim") dan umur (default 0) memakai ??. Juga demonstrasikan ?. dan ??=.

text
// TODO

void main() {
  // TODO: panggil dengan berbagai kombinasi null
}