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
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:
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
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 ?.:
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
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
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
// SALAH
void main() {
int? n;
// String s = n ?? 'nol'; // ERROR: int? ?? String
}// BENAR: default harus tipe yang kompatibel
void main() {
int? n;
int m = n ?? 0;
print(m);
}3. Berlebihan memakai ?.
// 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 ?? bhanya mengevaluasibjikaanull (lazy evaluation). Jadiconfig ?? 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 ??=.
// TODO
void main() {
// TODO: panggil dengan berbagai kombinasi null
}