Konstruktor adalah fungsi khusus yang digunakan untuk membuat instansi kelas, biasanya bertugas menginisialisasi properti. Kecuali konstruktor bawaan, semua konstruktor memiliki nama yang sama dengan nama kelas.
Klasifikasi konstruktor di Dart:
- Konstruktor Generatif (Generative)
- Konstruktor Bawaan (Default)
- Konstruktor Bernama (Named)
- Konstruktor Konstanta (Const)
- Konstruktor Pengalih (Redirecting)
- Konstruktor Pabrik (Factory)
- Konstruktor Pabrik Pengalih
- Sintaks konstruktor ringkas (Dart 3.13+)
- Konstruktor Utama (Primary Constructors, bidang minimalis + konstruktor)
1. Konstruktor Generatif Generative Constructor
Konstruktor paling dasar, berfungsi membuat instansi dan menginisialisasi variabel anggota, mendukung parameter inisialisasi this.variabel untuk menyederhanakan penugasan nilai.
class Point {
double x;
double y;
// Konstruktor generatif, this.x langsung menerima parameter untuk menugaskan variabel anggota
Point(this.x, this.y); // Langsung memberikan nilai ke x dan y
}
void main() {
final p = Point(10, 20);
print("(${p.x}, ${p.y})"); // (10, 20)
}
Code language: JavaScript (javascript)
2. Konstruktor Bawaan Default Constructor
Jika kelas tidak mendefinisikan konstruktor secara manual, Dart akan otomatis menyediakan konstruktor generatif tanpa parameter dan tanpa nama. Hal ini sama seperti bahasa sejenis C yaitu C++, Java, C# dan lainnya.
class PointA {
double x = 0;
double y = 0;
// Konstruktor bawaan implisit: PointA();
}
void main() {
final p = PointA(); // Otomatis memanggil konstruktor bawaan
print("(${p.x}, ${p.y})"); // (0.0, 0.0)
}
Code language: PHP (php)
Catatan: Jika kamu menulis konstruktor apapun secara manual, konstruktor bawaan akan hilang.
3. Konstruktor Bernama Named Constructor
Fungsi: Mendefinisikan banyak konstruktor dalam satu kelas dengan makna yang jelas; format NamaKelas.NamaKonstruktor()
const double xOrigin = 0;
const double yOrigin = 0;
class Point {
final double x;
final double y;
// Konstruktor generatif utama
Point(this.x, this.y);
// Konstruktor bernama: titik asal
Point.origin() : x = xOrigin, y = yOrigin;
}
void main() {
final p1 = Point(5, 6);
final p2 = Point.origin(); // Memanggil konstruktor bernama
print(p1.x); //5
print("Titik asal: (${p2.x}, ${p2.y})"); // (0,0)
}
Code language: PHP (php)
Aturan Penting
- Kelas turunan tidak mewarisi konstruktor bernama dari kelas induk; jika butuh konstruktor bernama yang sama di kelas turunan harus dibuat manual;
- Konstruktor bernama mendukung daftar inisialisasi untuk memberikan nilai variabel final.
4. Konstruktor Konstanta Const Constructor
Digunakan untuk membuat objek konstanta saat kompilasi, syaratnya:
- Semua variabel anggota diberi modifier
final - Tambahkan kata kunci
constpada konstruktor, saat pemanggilan pakaiconstuntuk menggunakan cache konstanta kembali. Jika tidak pakai const akan membuat instansi biasa.
class ImmutablePoint {
static const ImmutablePoint origin = ImmutablePoint(0, 0); // Statis milik kelas, semua kelas berbagi satu objek
final double x, y;
// Konstruktor konstanta bisa menginisialisasi x dan y yang bersifat final
const ImmutablePoint(this.x, this.y);
}
void main() {
// Konstanta kompilasi, menggunakan objek yang sama kembali
const p1 = ImmutablePoint(1, 2);
const p2 = ImmutablePoint(1, 2); // Nilai parameter harus sama, jika berbeda akan jadi objek berbeda
print(p1 == p2); // true
// Instansi biasa, objek baru
final p3 = ImmutablePoint(1, 2);
print(p1 == p3); // false
}Code language: PHP (php)
5. Konstruktor Pengalih Redirecting Constructor
Konstruktor yang meneruskan eksekusi ke konstruktor lain di kelas yang sama dengan sintaks : this(parameter), badan fungsi harus kosong.
class Point {
double x, y;
// Konstruktor utama
Point(this.x, this.y);
// Konstruktor pengalih: hanya kirim x, y tetap 0, arahkan ke konstruktor utama
Point.alongX(double x) : this(x, 0); // Panggil konstruktor bernama lalu kirim x ke konstruktor utama sekaligus tetapkan y=0
}
void main() {
final p = Point.alongX(9);
print("x=${p.x}, y=${p.y}"); // x=9, y=0
}
Code language: JavaScript (javascript)
6. Konstruktor Pabrik Factory Constructor
Menggunakan kata kunci factory, skenario penggunaan:
- Tidak selalu membuat objek baru (penggunaan cache kembali, mengembalikan instansi kelas turunan)
- Logika kompleks sebelum pembuatan objek (parsing JSON, validasi parameter). Batasan: tidak bisa mengakses
this
Contoh Singleton Cache Logger
class Logger {
final String name;
bool mute = false;
// Cache privat hanya bisa diakses dalam library
static final Map<String, Logger> _cache = {};
// Konstruktor pabrik: ambil dari cache terlebih dahulu
factory Logger(String name) {
return _cache.putIfAbsent(name, () => Logger._internal(name));
}
// Konstruktor pabrik: buat dari parsing json
factory Logger.fromJson(Map<String, dynamic> json) {
return Logger(json["name"].toString());
}
// Konstruktor generatif internal privat
Logger._internal(this.name);
void log(String msg) {
if (!mute) print(msg);
}
}
void main() {
final log1 = Logger("UI");
final log2 = Logger("UI");
print(log1 == log2); // true objek cache yang sama
final jsonLog = Logger.fromJson({"name": "Net"});
jsonLog.log("request success");
}
Code language: PHP (php)
7. Konstruktor Pabrik Pengalih Redirecting Factory
Format factory Nama() = KonstruktorKelasLain;, cocok untuk kelas abstrak yang mendelegasikan pembuatan instansi, menghindari penulisan parameter berulang.
abstract class Listenable {}
class _MergingListenable implements Listenable {
List<_MergingListenable> list;
_MergingListenable(this.list);
}
// Konstruktor pabrik pengalih, panggil konstruktor kelas privat internal
factory Listenable.merge(List<Listenable> list) = _MergingListenable;
Code language: PHP (php)
8. Pemisahan Konstruktor Constructor Tear-offs
Langsung gunakan konstruktor sebagai parameter fungsi tanpa menuliskan (), menggantikan fungsi anonim lambda dengan performa yang lebih baik.
Cara Disarankan
void main() {
final charCodes = [65, 66, 67];
// Konstruktor bernama String.fromCharCode
final strs = charCodes.map(String.fromCharCode);
print(strs); // (A, B, C)
// Pemisahan konstruktor tanpa nama pakai .new
final buffers = charCodes.map(StringBuffer.new);
}
Code language: PHP (php)
Tidak Disarankan: Lambda Berlebih
// Pembungkus berlebih, tidak disarankan
charCodes.map((code) => String.fromCharCode(code));
Code language: JavaScript (javascript)
9. Sintaks Konstruktor Ringkas Dart 3.13+ Concise Constructor
Di dalam kelas bisa menghilangkan nama kelas, langsung gunakan new / factory untuk definisi konstruktor tanpa tulis NamaKelas.xxx:
| Penulisan Tradisional | Singkatan |
|---|---|
Point(this.x,this.y) | new(this.x,this.y) |
Point.origin():x=0,y=0 | new origin():x=0,y=0 |
factory Point.clone() | factory clone() |
class Point {
double x, y;
// Singkatan konstruktor generatif tanpa nama
new(this.x, this.y);
// Singkatan konstruktor generatif bernama
new origin() : x = 0, y = 0;
// Singkatan konstruktor pabrik
factory clone(Point other) => new(other.x, other.y);
}
void main() {
final p = new(3, 4);
final origin = new origin();
final copy = p.clone(p);
}
Code language: PHP (php)
10. Tiga Cara Inisialisasi Variabel Instansi
1: Beri nilai langsung saat deklarasi
class PointA {
double x = 1.0;
double y = 2.0;
}
Code language: JavaScript (javascript)
2: Parameter Inisialisasi
this.variabel
Mendukung parameter opsional, parameter bernama, variabel nullable
class PointB {
final double x;
final double y;
// Parameter opsional posisi
PointB.opt([this.x = 0, this.y = 0]);
// Parameter bernama dengan nilai default
PointB.named({this.x = 5, this.y = 5});
}
Code language: PHP (php)
3: Daftar Inisialisasi Initializer List
Penugasan nilai setelah tanda titik dua :, dieksekusi sebelum badan konstruktor, tidak boleh mengakses this, mendukung assert untuk validasi parameter
class Point {
final double x;
final double y;
Point.fromJson(Map<String, double> json)
: x = json["x"]!,
y = json["y"]! {
print("Badan konstruktor dieksekusi, x=$x");
}
// Dengan validasi assert
Point.withAssert(this.x, this.y) : assert(x >= 0);
}
Code language: PHP (php)
11. Parameter Inisialisasi Bidang Privat Langsung (Dart3.12+)
Variabel privat awalan garis bawah, tulis parameter konstruktor this._bidang, saat panggil dari luar gunakan nama publik tanpa garis bawah.
class Point {
final double _x;
final double _y;
// Internal pakai _x, panggil dari luar tulis x:10
Point({required this._x, this._y = 0});
}
void main() {
final p = Point(x: 10); // Tidak tulis _x, langsung x
print(p._x); // 10
}
Code language: PHP (php)
Gunakan nama asli variabel privat di daftar inisialisasi:
class Point {
final double _x;
Point({required this._x}) : assert(_x > 0);
}
Code language: JavaScript (javascript)
12. Konstruktor Kelas Induk dan Aturan Pewarisan Konstruktor
- Kelas turunan tidak mewarisi konstruktor apapun dari kelas induk;
- Urutan eksekusi konstruktor: daftar inisialisasi → konstruktor induk → badan konstruktor turunan;
- Jika kelas induk tidak punya konstruktor bawaan tanpa parameter, kelas turunan wajib gunakan
super()untuk tentukan konstruktor induk secara manual.
Contoh Pemanggilan super Dasar
Sama seperti Java, gunakan super untuk merujuk kelas dasar, sedangkan C# pakai base.
class Person {
final String name;
Person(this.name);
Person.fromMap(Map map) : name = map["name"];
}
class Employee extends Person {
int id;
// Panggil konstruktor bernama induk
Employee(Map data) : super.fromMap(data), id = data["id"];
}
Code language: PHP (php)
Catatan: Ekspresi parameter super tidak boleh menggunakan
this.
Parameter Super (Dart2.17+, sederhanakan pengiriman parameter ke induk)
Gunakan super.variabel untuk meneruskan parameter langsung ke konstruktor induk tanpa tulis super(x,y) secara manual
class Vector2d {
final double x, y;
Vector2d(this.x, this.y);
}
class Vector3d extends Vector2d {
final double z;
// super.x super.y otomatis kirim ke konstruktor induk
Vector3d(super.x, super.y, this.z);
}
// Konstruktor bernama induk + parameter super bernama
class Vector3dYZ extends Vector2d {
final double z;
Vector3dYZ({required super.y, required this.z}) : super.named(x: 0);
}
Code language: JavaScript (javascript)