Constructor Dasar
Membuat object dengan nilai awal lewat constructor.
Constructor: cara lahirnya objek
Di modul sebelumnya, membuat objek terasa canggung: var budi = Siswa(); lalu mengisi field satu per satu. Bagaimana kalau lupa mengisi nama? Objek setengah jadi berkeliaran. Constructor adalah "proses kelahiran" objek: cara resmi membuat objek sekaligus mengisi field wajibnya.
Analogi: constructor itu seperti formulir pendaftaran kelahiran. Bayi (objek) tidak keluar begitu saja; ia lahir lewat prosedur yang memastikan nama dan data penting terisi.
Kenapa constructor ada?
Dua alasan: menjamin objek valid sejak lahir (tidak ada objek setengah jadi) dan meringkas pembuatan objek (satu baris, bukan lima). Constructor juga menyelesaikan masalah null safety: field non-nullable bisa diisi lewat constructor tanpa nilai default palsu.
Constructor dasar
class Siswa {
String nama;
int umur;
// Constructor: nama sama dengan class, tanpa return type
Siswa(this.nama, this.umur);
void perkenalkan() {
print('Halo, aku $nama ($umur tahun)');
}
}
void main() {
var budi = Siswa('Budi', 17); // langsung lengkap!
var ani = Siswa('Ani', 16);
budi.perkenalkan();
ani.perkenalkan();
}Keajaiban this.nama: sintaks ringkas yang artinya "parameter constructor langsung disimpan ke field". Tanpa ini kamu harus menulis:
// Versi panjang yang setara (tidak perlu ditulis)
Siswa(String namaParam, int umurParam) {
nama = namaParam;
umur = umurParam;
}Contoh kedua, constructor dengan named parameter (pola favorit Flutter):
class Produk {
String nama;
double harga;
int stok;
Produk({required this.nama, required this.harga, this.stok = 0});
double totalNilai() => harga * stok;
}
void main() {
var laptop = Produk(nama: 'Laptop', harga: 15000000, stok: 5);
var mouse = Produk(nama: 'Mouse', harga: 150000); // stok default 0
print('${laptop.nama}: ${laptop.totalNilai()}');
print('${mouse.nama}: stok ${mouse.stok}');
}Perhatikan: field tidak lagi butuh nilai default palsu (nama = ''). Constructor mengisi semuanya, dan required menjamin pemanggil tidak lupa.
Initializer list: komputasi sebelum badan
Kadang field butuh dihitung dari parameter sebelum objek jadi:
class Lingkaran {
double radius;
double luas;
// Initializer list (: ...) jalan SEBELUM badan constructor
Lingkaran(this.radius) : luas = 3.14 * radius * radius;
void info() => print('r=$radius, luas=$luas');
}
void main() {
Lingkaran(10).info(); // r=10.0, luas=314.0
}Aturan: field final WAJIB diisi di initializer list atau langsung, tidak bisa di badan constructor.
Kesalahan umum
1. Constructor dengan return type
// SALAH
class Siswa {
String nama = '';
// void Siswa() {} // ERROR: constructor tidak boleh punya return type
}// BENAR
class Siswa {
String nama;
Siswa(this.nama);
}2. Field final diisi di badan constructor
// SALAH
class Siswa {
final String nama;
// Siswa(String n) {
// nama = n; // ERROR: final harus di initializer
// }
}// BENAR
class Siswa {
final String nama;
Siswa(this.nama); // this.nama termasuk initializer, boleh
}this.nama di parameter dihitung sebagai inisialisasi langsung, jadi aman untuk final.
3. Argumen named tanpa nama
// SALAH
class Produk {
String nama;
Produk({required this.nama});
}
void main() {
// var p = Produk('Laptop'); // ERROR: harus Produk(nama: 'Laptop')
}// BENAR
void main() {
var p = Produk(nama: 'Laptop');
print(p.nama);
}Kesimpulan
Constructor = gerbang kelahiran objek yang menjamin field terisi. Pola this.x untuk positional, {required this.x} untuk named (gaya Flutter). Ingat: constructor tanpa return type, dan field final diisi via initializer.
Catatan teknis: Setiap class otomatis punya default constructor tanpa argumen (
Siswa()) SELAMA kamu tidak menulis constructor sendiri. Begitu kamu menulis satu constructor, default-nya hilang.
Tantangan
Class Mahasiswa
Buat class Mahasiswa dengan field final nim, nama, constructor Mahasiswa(this.nim, this.nama), dan method sapa() yang mencetak sapaan. Buat 2 object.
// TODO: class Mahasiswa
void main() {
// TODO
}