Variabel Dart

    Variabel

    Pelajari variabel di Dart. Berikut contoh pembuatan dan inisialisasi variabel:

    var name = 'Jack';

    Variabel menyimpan referensi. Variabel bernama name menampung sebuah referensi yang menunjuk objek string bernilai “Bob”.

    Referensi adalah alamat di memori. Agar mudah menyimpan data, setiap area memori diberi alamat unik, layaknya nomor rumah di jalan.

    Kompiler akan menyimpulkan tipe name secara otomatis menjadi String, namun kamu juga bisa menentukan tipe secara manual untuk mengubah hasil inferensi. Jika variabel perlu menampung objek dengan berbagai tipe, deklarasikan tipenya sebagai Object (jika perlu bisa pakai dynamic).

    Object name = 'Jack';

    Cara lain adalah menentukan tipe secara eksplisit (contohnya kita tahu nama berupa teks, bisa disimpan tipe String, jadi langsung tulis tipe string):

    String name = 'Jack';

    Null Safety (Keamanan Nilai Kosong)

    Null safety mencegah error akibat salah mengakses variabel bernilai null, error ini disebut kesalahan dereferensi null (null dereference error). Error muncul saat kamu mengakses properti atau memanggil method dari ekspresi hasilnya bernilai null.

    Ada pengecualian: jika null asli mendukung properti atau method tersebut (contoh toString(), hashCode), tidak akan muncul error. Dengan null safety, kompiler Dart bisa mendeteksi potensi error ini saat kompilasi.

    Pembaca yang sudah berpengalaman pemrograman pasti tahu error referensi null sangat umum. Jika error ini bisa dicegah sejak tahap kompilasi, stabilitas dan ketahanan program akan meningkat drastis.

    Contoh: anggap kamu ingin mengambil nilai absolut variabel tipe int bernama i. Jika i bernilai null, menjalankan i.abs() akan memicu error dereferensi null. Di bahasa pemrograman lain, kode ini hanya error saat program berjalan; sedangkan kompiler Dart langsung melarang pemanggilan ilegal ini dan menangkap masalah lebih awal.

    Tiga perubahan utama dari null safety:

    1 Tipe dapat null: saat menentukan tipe, kamu bisa mengontrol apakah tipe boleh menyimpan null dengan menambahkan tanda tanya di akhir tipe.

    String? name  // Tipe dapat null: nilainya bisa null atau string
    String name   // Tipe tidak dapat null: tidak boleh null, hanya menampung string

    Di beberapa bahasa pemrograman, string name bisa menampung null, tapi di Dart tidak bisa. Jika ingin simpan null harus pakai tipe string?.

    2 Variabel wajib diinisialisasi sebelum dipakai. Variabel tipe dapat null nilai defaultnya adalah null, sama saja dengan sudah diinisialisasi; tipe tidak dapat null tidak punya nilai default, wajib kamu beri nilai awal secara manual. Dart tidak izinkan akses variabel yang belum diinisialisasi untuk mencegah masalah.

    void main() {
      int year;        // Error: variabel non-null belum diinisialisasi
      print(year);     // Error kompilasi: year belum diberi nilai awal
    }

    Kode di atas akan error saat kompilasi

    C:\dartdemo\firstdart>dart run
    Building package executable...
    Failed to build firstdart:firstdart:
    bin/firstdart.dart:7:9: Error: Non-nullable variable 'year' must be assigned before it can be used.
      print(year);     // Error kompilasi: year belum diinisialisasi
            ^^^^

    Sedangkan variabel tipe dapat null boleh tulis seperti ini:

    void main() {
      int? age;        // Variabel dapat null, nilai default null
      print(age);      // Keluar null tanpa error
      
      //age = 18;        // Pemberian nilai manual
      //print(age);      // Keluar 18
    }

    3 Tidak boleh langsung akses properti atau panggil method dari ekspresi tipe dapat null. Ada pengecualian lagi: properti dan method asli milik null (hashCode, toString()) tetap boleh dipanggil.

    void main() {
      String? name; // Tipe dapat null, nilai default null
    
      // Error: langsung akses length akan gagal
      // print(name.length);
    
      // Benar: boleh panggil method bawaan null
      print(name.toString());  // Keluar "null"
      print(name.hashCode);    // Keluar bilangan bulat
    
      // Benar: pakai operator null safety
      print(name?.length);     // Keluar null tanpa error
    }

    Nilai Default

    Variabel tipe dapat null yang tidak diberi nilai manual secara otomatis bernilai null. Bahkan variabel tipe angka defaultnya juga null,

    karena di Dart angka dan semua data lainnya pada dasarnya adalah objek.

    void main() {
      int? lineCount;
      assert(lineCount == null);
    }

    Catatan: kode produksi akan mengabaikan pengecekan assert(); saat pengembangan, jika kondisi di dalam assert() salah program akan lempar exception

    Setelah aktif null safety, variabel non-null wajib diinisialisasi sebelum dipakai:

    int lineCount = 0;

    Variabel lokal tidak harus diberi nilai di baris deklarasi, tapi wajib diberi nilai sebelum dipakai. Kode di bawah valid karena Dart bisa analisis saat jalankan print(), lineCount pasti sudah punya nilai non-null:

    int lineCount;
    
    if (weLikeToCount) {
      lineCount = countLines();
    } else {
      lineCount = 0;
    }
    
    print(lineCount);
    

    Catatan kode di atas lineCount = countLines(); dan lineCount = 0; adalah pemberian nilai ke lineCount, bukan penggunaan variabel. Penggunaan artinya membaca nilai yang tersimpan. Contoh kode di bawah akan error:

    void main() {
    	int lineCount;
    
    	print(lineCount);
    }

    Error kompilasi

    Variabel tingkat atas dan anggota kelas pakai inisialisasi tertunda: logika pemberian nilai hanya dijalankan saat pertama kali variabel diakses.

    Modifier late pada variabel

    Modifier late punya dua skenario penggunaan:

    1. Deklarasi variabel non-null yang akan diberi nilai nanti;
    2. Membuat inisialisasi tertunda variabel.

    Sebagian besar kasus analisis alur Dart bisa mendeteksi variabel non-null sudah dapat nilai sebelum dipakai. Tapi ada skenario analisis gagal, yang paling umum variabel global dan variabel instance: kompiler biasanya tidak bisa pastikan apakah sudah diinisialisasi sehingga muncul error.

    Jika kamu yakin variabel pasti diberi nilai sebelum dipakai tapi kompiler tidak bisa deteksi, tambah modifier late untuk hilangkan error:

    Contoh di bawah description adalah variabel global, kompiler tidak bisa tahu apakah akan diberi nilai, tapi kamu yakin pasti ada nilai pakai late:

    late String description;
    
    void main() {
      description = 'Feijoada!';
      print(description);
    }
    

    Peringatan

    Jika deklarasi variabel pakai late tapi tidak pernah diberi nilai, saat akses variabel akan muncul exception runtime.

    Jika kamu beri nilai awal saat deklarasi variabel late, kode inisialisasi hanya dijalankan saat variabel pertama kali diakses. Inisialisasi tertunda sangat berguna dua kondisi:

    1. Variabel mungkin tidak pernah dipakai dan operasi inisialisasi memakan sumber daya besar;
    2. Saat inisialisasi variabel instance, logika inisialisasi perlu akses this.

    Contoh di bawah jika variabel temperature tidak pernah dipakai, fungsi berat readThermometer() tidak akan pernah dijalankan:

    // Fungsi readThermometer() hanya dipanggil saat pertama kali akses temperature
    late String temperature = readThermometer(); // Inisialisasi tertunda
    

    final dan const

    Jika tidak ingin nilai variabel diubah, pakai final atau const; keduanya bisa dipakai sendiri atau bersama anotasi tipe menggantikan var.

    • Variabel final hanya boleh diberi nilai satu kali;
    • Variabel const adalah konstanta waktu kompilasi (variabel const secara implisit punya sifat final).

    Catatan

    Anggota instance boleh pakai final, tapi tidak boleh const; konstanta tingkat kelas gunakan static const.

    Contoh deklarasi variabel final:

    final name = 'Jack'; // Tanpa anotasi tipe
    final String nickname = 'Jason';
    

    Kamu tidak bisa ubah nilai variabel final, kompiler langsung keluarkan error:

    void main() {
    	final name = 'Jack'; // Tanpa anotasi tipe
    	final String nickname = 'Jason';
    	
    	name = 'Alice'; // Error: variabel final hanya boleh diassign satu kali
    }
    C:\dartdemo\firstdart>dart run
    Building package executable...
    Failed to build firstdart:firstdart:
    bin/firstdart.dart:6:2: Error: Can't assign to the final variable 'name'.
            name = 'Alice'; // Error: variabel final hanya boleh diassign satu kali

    const untuk buat konstanta waktu kompilasi. Jika konstanta di dalam kelas harus tambah static jadi static const. Saat deklarasi variabel const nilai yang diberikan harus sudah diketahui saat kompilasi: angka, literal string, variabel const lain atau hasil operasi aritmatika angka konstanta:

    const bar = 1000000; // Satuan tekanan (dyne/cm²)
    const double atm = 1.01325 * bar; // Tekanan atmosfer standar
    

    Kata kunci const tidak hanya buat variabel konstanta, kamu juga bisa pakai buat objek konstanta atau konstruktor yang menghasilkan instance konstanta. Semua variabel bisa menerima objek konstanta sebagai nilai.

    var foo = const [];
    final bar = const [];
    const baz = []; // Sama dengan const []
    

    Dalam ekspresi assign variabel const kata kunci const bisa dihilangkan seperti contoh baz di atas.

    Meskipun variabel pernah simpan objek konstanta, jika bukan final maupun const, referensinya bisa diganti:

    foo = [1, 2, 3]; // foo awalnya menunjuk array kosong konstanta, sekarang ganti referensi
    

    Tapi variabel const tidak boleh diassign ulang, kompiler akan error:

    // Analisis statis: kode salah
    baz = [42]; // Error: variabel konstanta tidak boleh diassign ulang
    

    Saat definisikan konstanta bisa pakai pengecekan tipe, casting tipe (is, as), collection if, operator spread (..., ...?):

    void main() {
    	const Object i = 3; // i konstanta tipe Object yang simpan nilai int
    	const list = [i as int]; // Pakai casting tipe
    	const map = {if (i is int) i: 'int'}; // Pakai is dan collection if
    	const set = {if (list is List<int>) ...list}; // Gabung operator spread
    }

    Catatan

    Objek pakai modifier final referensinya tidak bisa diganti, tapi field di dalam objek bisa diubah; berbeda dengan objek const objek dan semua data di dalamnya tidak bisa diubah sama sekali (immutable penuh).

    Untuk info lebih lanjut membuat koleksi konstanta pakai const lihat dokumentasi list, map dan kelas.

    * Variabel wildcard

    Keterangan versi: variabel wildcard minimal butuh Dart versi 3.7.

    Variabel bernama _ adalah variabel lokal/parameter tanpa binding, hanya berfungsi sebagai placeholder. Jika ada ekspresi inisialisasi ekspresi tetap dijalankan tapi kamu tidak bisa baca nilai yang disimpan variabel tersebut. Di satu scope bisa buat banyak variabel bernama _ tanpa konflik nama.

    Apa itu variabel wildcard

    Di Dart _ underscore tunggal adalah variabel wildcard:

    1. Dipakai terima nilai yang tidak perlu dipakai, beri sinyal ke kompiler “variabel ini tidak akan dibaca atau dipakai”;
    2. Kompiler tidak keluarkan peringatan “variabel didefinisikan tapi tidak dipakai”;
    3. Tidak boleh baca _ (akan error), hanya untuk buang data tidak dipakai.
    // Ambil nilai ke-1 dan ke-3 saja, yang kedua buang pakai _
    final [a, _, c] = [10, 20, 30];
    print(a); // 10
    print(c); // 30
    // print(_); // Error tidak boleh baca wildcard

    Deklarasi tingkat atas dan anggota kelas yang pengaruh akses privat library tidak boleh pakai variabel wildcard. Hanya bisa pakai di dalam blok scope contoh di bawah:

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *