Apa itu konstruktor

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:

  1. Konstruktor Generatif (Generative)
  2. Konstruktor Bawaan (Default)
  3. Konstruktor Bernama (Named)
  4. Konstruktor Konstanta (Const)
  5. Konstruktor Pengalih (Redirecting)
  6. Konstruktor Pabrik (Factory)
  7. Konstruktor Pabrik Pengalih
  8. Sintaks konstruktor ringkas (Dart 3.13+)
  9. 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:

  1. Semua variabel anggota diberi modifier final
  2. Tambahkan kata kunci const pada konstruktor, saat pemanggilan pakai const untuk 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:

  1. Tidak selalu membuat objek baru (penggunaan cache kembali, mengembalikan instansi kelas turunan)
  2. 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 TradisionalSingkatan
Point(this.x,this.y)new(this.x,this.y)
Point.origin():x=0,y=0new 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

  1. Kelas turunan tidak mewarisi konstruktor apapun dari kelas induk;
  2. Urutan eksekusi konstruktor: daftar inisialisasi → konstruktor induk → badan konstruktor turunan;
  3. 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)

Tinggalkan Balasan

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