Masukkan Password
37 Dart Constructor with features | Constructor in Dart | Dart Tutorials #36
Materi ini membahas constructor di Dart, dan ini termasuk konsep yang sangat penting sebelum kamu masuk lebih jauh ke Flutter.
Aku akan menjelaskannya dari masalah yang ingin diselesaikan constructor → pengertian constructor → 12 fitur penting → contoh → koreksi bagian transkrip yang kurang tepat.
1. Apa itu constructor?
Constructor adalah mekanisme khusus pada class yang digunakan untuk membuat dan menginisialisasi object.
Contoh paling sederhana:
class Person {
String name;
int age;
Person(this.name, this.age);
}
Kemudian:
void main() {
Person p = Person("Sam", 21);
}
Ketika:
Person("Sam", 21)
dijalankan, Dart membuat object Person dan menginisialisasi:
name = "Sam"
age = 21
Jadi constructor sangat erat hubungannya dengan object creation dan initialization.
2. Kenapa kita membutuhkan constructor?
Untuk memahami manfaat constructor, kita lihat masalah yang terjadi kalau kita menggunakan method biasa untuk menginisialisasi object.
Misalnya:
class Person {
String? name;
int? age;
void setData(String name, int age) {
this.name = name;
this.age = age;
}
void showData() {
print("Name: $name");
print("Age: $age");
}
}
Kemudian:
void main() {
Person p = Person();
p.setData("Sam", 21);
p.showData();
}
Hasil:
Name: Sam
Age: 21
Kelihatannya tidak masalah.
Tetapi ada masalah.
3. Masalah pertama: kita bisa lupa memanggil method initialization
Misalnya programmer menulis:
void main() {
Person p = Person();
// lupa p.setData()
p.showData();
}
Karena name dan age nullable:
String? name;
int? age;
hasilnya:
Name: null
Age: null
Object berhasil dibuat, tetapi datanya belum diinisialisasi.
Bayangkan ada 100 object:
Person p1 = Person();
Person p2 = Person();
Person p3 = Person();
// ...
Person p100 = Person();
Kemudian setiap object harus diingat untuk dipanggil:
p1.setData(...);
p2.setData(...);
p3.setData(...);
Mudah sekali terjadi kesalahan.
4. Masalah kedua: null safety
Misalnya kita ingin data Person tidak boleh null.
Kita tulis:
class Person {
String name;
int age;
}
Dart akan memberikan error karena field non-nullable harus diinisialisasi.
Kita memang bisa menggunakan:
class Person {
late String name;
late int age;
}
Kemudian:
Person p = Person();
p.showData();
Kalau ternyata name dan age belum pernah diisi, akan terjadi runtime error karena late menjanjikan:
“Tenang, saya akan mengisi variable ini sebelum digunakan.”
Kalau janji itu tidak dipenuhi, program gagal saat runtime.
5. Constructor menjadi solusi
Constructor memungkinkan kita mengatakan:
“Object
Persontidak boleh dibuat sebelumnamedanagediberikan.”
Contohnya:
class Person {
String name;
int age;
Person(this.name, this.age);
}
Sekarang:
Person p = Person("Sam", 21);
Data langsung tersedia sejak object dibuat.
Dan ini:
Person p = Person();
akan error karena name dan age wajib diberikan.
Jadi constructor membantu kita membuat object dalam kondisi yang sudah valid sejak awal.
6. Constructor adalah special member, tetapi bukan method biasa
Video menyebut constructor sebagai “special method”.
Untuk pemahaman dasar, boleh menganggapnya begitu, tetapi secara teknis constructor bukan method biasa.
Constructor memiliki aturan khusus.
Ada tiga ciri utama.
7. Ciri pertama: nama constructor sama dengan nama class
Misalnya class:
class Person {
}
Constructor:
Person() {
}
Namanya:
Person
harus sama dengan class:
Person
Contoh:
class Student {
Student() {
print("Student dibuat");
}
}
Benar.
Sedangkan:
class Student {
Person() {
}
}
itu bukan constructor Student.
Itu akan dianggap sebagai method bernama Person dan, jika tidak diberi return type, return type-nya dapat diinfer sebagai dynamic.
Jadi hati-hati.
8. Huruf besar-kecil sangat berpengaruh
Misalnya:
class ABC {
ABC() {
print("Constructor");
}
}
Ini constructor.
Tetapi:
class ABC {
abc() {
print("Hello");
}
}
abc() bukan constructor, karena nama class adalah:
ABC
sedangkan method:
abc
berbeda karena Dart case-sensitive.
9. Ciri kedua: constructor tidak mempunyai return type
Constructor tidak boleh ditulis:
class Person {
void Person() { // ❌
}
}
Juga tidak:
class Person {
int Person() { // ❌
}
}
Cukup:
class Person {
Person() {
}
}
Jangan menulis void.
10. Tetapi apakah constructor “mengembalikan object”?
Ini bagian transkrip yang perlu sedikit diluruskan.
Secara konsep pemula, memang ketika kita menulis:
Person p = Person();
hasil dari ekspresi Person() adalah sebuah instance Person.
Tetapi jangan memahami constructor seperti function biasa:
int add() {
return 10;
}
Constructor tidak ditulis dengan:
return object;
dan tidak memiliki return type yang kita deklarasikan.
Jadi lebih aman mengingat:
Constructor digunakan untuk menghasilkan/menginisialisasi instance, tetapi constructor bukan function biasa yang memiliki return statement.
11. Ciri ketiga: constructor dipanggil ketika object dibuat
Misalnya:
class Person {
Person() {
print("Constructor dijalankan");
}
}
Kemudian:
void main() {
Person p = Person();
}
Output:
Constructor dijalankan
Kita tidak menulis:
p.Person();
Tidak seperti method.
Constructor dijalankan sebagai bagian dari proses pembuatan object:
Person p = Person();
12. Constructor dipanggil satu kali untuk satu proses pembuatan object
Misalnya:
void main() {
Person p1 = Person();
Person p2 = Person();
Person p3 = Person();
}
Ada tiga object yang dibuat.
Constructor akan dijalankan tiga kali:
Object 1 → constructor
Object 2 → constructor
Object 3 → constructor
Tetapi untuk satu object tertentu, constructor-nya tidak dipanggil berkali-kali hanya karena object tersebut digunakan berkali-kali.
13. Default constructor
Sekarang masuk ke salah satu bagian paling penting.
Misalnya kita memiliki:
class Person {
}
Kita tidak menulis constructor sama sekali.
Tetapi:
Person p = Person();
tetap valid.
Kenapa?
Karena Dart menyediakan unnamed default constructor secara implisit ketika class tidak mendeklarasikan constructor yang menghalangi hal tersebut.
Secara konsep kamu bisa membayangkannya seperti:
class Person {
Person();
}
Constructor ini:
- unnamed
- tidak memiliki parameter
- tidak melakukan apa-apa secara khusus
14. Kalau kita sudah membuat constructor sendiri?
Misalnya:
class Person {
Person(String name, int age);
}
Sekarang:
Person p = Person();
akan error.
Kenapa?
Karena constructor yang tersedia membutuhkan:
String name
int age
Jadi harus:
Person p = Person("Sam", 21);
Ingat aturan penting:
Jika kamu mendeklarasikan constructor sendiri, jangan menganggap Dart tetap menyediakan constructor kosong secara otomatis.
15. Traditional constructor vs shorthand constructor
Misalnya kita ingin melakukan:
name = name;
age = age;
Kita bisa menulis:
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
}
Ini valid.
Tetapi Dart menyediakan shorthand yang jauh lebih praktis:
class Person {
String name;
int age;
Person(this.name, this.age);
}
Ini disebut generative constructor dengan initializing formal parameters.
Video menyebutnya “syntactic sugar”, dan itu cukup tepat sebagai istilah pembelajaran.
16. Apa arti this.name?
Bagian ini penting.
Dalam:
Person(this.name, this.age);
this.name berarti:
parameter constructor ini langsung digunakan untuk menginisialisasi field
namemilik object saat ini.
Secara konsep mirip dengan:
Person(String name, int age) {
this.name = name;
this.age = age;
}
Jadi:
Person("Sam", 21)
"Sam" → this.name
21 → this.age
Hasil:
Person object
├── name = "Sam"
└── age = 21
17. Kenapa cara ini bagus untuk null safety?
Perhatikan:
class Person {
String name;
int age;
Person(this.name, this.age);
}
Dart tahu bahwa ketika object selesai dibuat:
name → sudah punya String
age → sudah punya int
Karena constructor membutuhkan kedua nilai tersebut.
Jadi kita tidak perlu:
String? name;
int? age;
dan tidak perlu:
late String name;
late int age;
Ini salah satu alasan constructor sangat penting dalam Dart modern.
18. Constructor bisa menggunakan positional parameter
Contoh:
class Person {
String name;
int age;
Person(this.name, this.age);
}
Pemanggilan:
Person p = Person("Sam", 21);
Urutannya:
"Sam" → name
21 → age
Karena ini positional parameter.
19. Constructor bisa menggunakan named parameter
Kita bisa menulis:
class Person {
String name;
int age;
Person({
required this.name,
required this.age,
});
}
Pemanggilan:
Person p = Person(
name: "Sam",
age: 21,
);
Sekarang berdasarkan nama:
name: "Sam" → name
age: 21 → age
Urutan bisa dibolak-balik:
Person(
age: 21,
name: "Sam",
);
tetap valid.
20. Constructor bisa menggabungkan positional dan named parameter
Contoh:
class Person {
String name;
int age;
String? city;
Person(
this.name, {
required this.age,
this.city,
});
}
Pemanggilan:
Person p = Person(
"Sam",
age: 21,
city: "Madiun",
);
Di sini:
"Sam"
adalah positional argument.
Sedangkan:
age: 21
city: "Madiun"
adalah named arguments.
Ingat aturan yang sudah kita pelajari:
positional → sebelum named
named → setelah positional
21. required pada constructor
Contoh:
class Person {
String name;
int age;
Person({
required this.name,
required this.age,
});
}
Karena required, ini tidak boleh:
Person p = Person();
Harus:
Person p = Person(
name: "Sam",
age: 21,
);
Dan perhatikan:
required this.name
bukan berarti name nullable.
Justru:
String name
adalah non-nullable.
Artinya:
parameter wajib diberikan dan nilainya tidak boleh null.
22. Dart tidak mendukung constructor overloading tradisional
Ini sangat penting.
Misalnya kamu mencoba:
class Person {
Person() {}
Person(String name) {}
}
Tidak diperbolehkan.
Kenapa?
Karena Dart tidak mempunyai traditional constructor overloading seperti Java/C++.
Dart tidak mengatakan:
“Oh, yang satu punya 0 parameter dan yang satu punya 1 parameter, jadi saya pilih berdasarkan jumlah argument.”
Tidak seperti itu.
23. Solusinya: named constructor
Dart menyediakan named constructor.
Contoh:
class Person {
Person() {}
Person.fromName(String name) {
print(name);
}
}
Sekarang kita punya dua constructor yang berbeda:
Person()
Person.fromName(...)
Membuat object menggunakan constructor pertama:
Person p1 = Person();
Menggunakan constructor kedua:
Person p2 = Person.fromName("Sam");
Perhatikan:
Person
↓
.fromName
fromName adalah nama constructor.
24. Named constructor sangat penting di Flutter
Kamu akan sering melihat pola seperti:
SomeClass.fromJson(...)
atau constructor dengan nama tertentu.
Contohnya dalam model:
class User {
String name;
int age;
User(this.name, this.age);
User.fromJson(Map<String, dynamic> json)
: name = json["name"],
age = json["age"];
}
Kemudian:
User user = User.fromJson(jsonData);
Ini adalah salah satu pola yang sangat umum ketika bekerja dengan JSON/API.
25. Bisa punya banyak named constructor
Misalnya:
class Person {
String name;
int age;
Person(this.name, this.age);
Person.guest()
: name = "Guest",
age = 0;
Person.fromName(this.name)
: age = 0;
}
Sekarang:
Person p1 = Person("Sam", 21);
Person p2 = Person.guest();
Person p3 = Person.fromName("Mark");
Satu class dapat mempunyai beberapa constructor selama nama constructor-nya berbeda.
Person()
Person.guest()
Person.fromName()
Person.fromJson()
...
26. Constructor bisa dibuat private
Seperti yang baru kita pelajari tentang private member.
Kalau kita tulis:
class Person {
Person._private() {
print("Private constructor");
}
}
Constructor:
_private
diawali _, sehingga private terhadap library.
Constructor tersebut hanya bisa digunakan dari library yang sesuai.
27. Kenapa constructor private berguna?
Salah satu kegunaannya adalah ketika kita tidak ingin sembarang kode membuat object dari class tersebut.
Misalnya sebuah class hanya boleh membuat instance melalui method tertentu.
Ini juga sering menjadi bagian dari implementasi Singleton pattern.
Contoh sederhana:
class Database {
Database._internal();
static final Database instance = Database._internal();
}
Kemudian kita menggunakan:
Database db = Database.instance;
Bukan:
Database db = Database();
Karena constructor unnamed public tidak tersedia.
Untuk sekarang kamu cukup pahami idenya. Singleton sendiri bisa dipelajari lebih dalam nanti.
28. Constructor tidak diwariskan oleh child class
Ini bagian inheritance.
Misalnya:
class Father {
Father(int age) {
print("Father: $age");
}
}
Kemudian:
class Son extends Father {
Son() {
print("Son");
}
}
Ini akan bermasalah.
Kenapa?
Karena Father tidak memiliki constructor kosong:
Father()
Constructor Son() secara default perlu menginisialisasi superclass.
29. Child constructor harus memanggil superclass constructor
Kita bisa menggunakan:
super
Contoh:
class Father {
Father(int age) {
print("Father: $age");
}
}
class Son extends Father {
Son() : super(10) {
print("Son");
}
}
Sekarang:
void main() {
Son s = Son();
}
Output:
Father: 10
Son
Urutannya:
Son()
↓
super(10)
↓
Father(10)
↓
Father constructor selesai
↓
Son constructor
Jadi superclass constructor dijalankan terlebih dahulu.
30. Kenapa constructor tidak diwariskan?
Misalnya:
class Father {
Father(int age);
}
Kemudian:
class Son extends Father {
}
Jangan berpikir bahwa Son otomatis memiliki:
Son(int age)
Tidak.
Constructor Father tidak otomatis menjadi constructor Son.
Child class harus memiliki constructor-nya sendiri dan mengatur pemanggilan superclass constructor jika diperlukan.
31. Factory constructor
Ini salah satu bagian yang agak advanced.
Video mengatakan:
factory constructor adalah pengecualian karena dapat mengembalikan object.
Secara konsep dasar, benar bahwa factory constructor memiliki aturan return yang berbeda dari generative constructor biasa.
Contoh:
class Person {
final String name;
Person(this.name);
factory Person.guest() {
return Person("Guest");
}
}
Pemanggilan:
Person p = Person.guest();
Factory constructor dapat mengembalikan instance yang sesuai.
Misalnya:
factory Person.fromCache() {
return someExistingPerson;
}
Bahkan secara konsep factory tidak harus membuat instance baru setiap kali dipanggil.
32. Bedakan generative constructor dan factory constructor
Untuk sekarang:
Generative constructor
Person(this.name);
Secara langsung menghasilkan/menginisialisasi instance class tersebut.
Factory constructor
factory Person.guest() {
return Person("Guest");
}
Factory memberikan kontrol lebih besar terhadap object yang dikembalikan.
Misalnya:
- mengembalikan object yang sudah ada
- memilih subclass
- melakukan caching
- membuat object berdasarkan kondisi tertentu
Factory sangat sering muncul ketika kamu belajar design pattern, model JSON, singleton, dan Flutter/Dart yang lebih lanjut.
33. Constructor bisa memanggil constructor lain
Ini disebut constructor redirection.
Misalnya:
class Person {
String name;
int age;
Person(this.name, this.age);
Person.guest() : this("Guest", 0);
}
Perhatikan:
Person.guest() : this("Guest", 0);
this(...) di sini bukan this yang berarti object saat ini dalam body method.
Dalam konteks initializer constructor,:
this(...)
berarti:
panggil constructor lain dari class yang sama.
Jadi:
Person.guest()
mengarahkan ke:
Person("Guest", 0)
34. Kenapa constructor redirection berguna?
Misalnya kita punya constructor utama:
Person(this.name, this.age);
Kemudian kita ingin membuat constructor khusus untuk guest:
Person.guest() : this("Guest", 0);
Daripada menulis ulang:
Person.guest() {
name = "Guest";
age = 0;
}
kita cukup mengarahkan ke constructor utama.
Hasilnya lebih rapi.
35. Bedakan this(...) dan super(...)
Ini sangat penting.
this(...)
Memanggil constructor lain di class yang sama.
Person.guest() : this("Guest", 0);
Artinya:
Person.guest()
↓
Person(...)
super(...)
Memanggil constructor superclass/parent.
class Son extends Father {
Son() : super(10);
}
Artinya:
Son()
↓
Father(10)
Jadi:
this(...) → constructor class sendiri
super(...) → constructor parent/superclass
36. Dua jenis this yang perlu kamu bedakan
Kamu akan melihat:
this.name
dan:
this(...)
Keduanya berbeda konteks.
this.name
Mengacu pada member object saat ini.
Person(String name) {
this.name = name;
}
Artinya:
field
namemilik object ini.
this(...)
Dalam constructor initializer:
Person.guest() : this("Guest", 0);
artinya:
redirect ke constructor lain.
37. Dua belas poin constructor dalam satu tabel
Sekarang kita rangkum semua materi video:
| No | Fitur | Intinya |
|---|---|---|
| 1 | Nama constructor | Sama dengan nama class untuk unnamed constructor |
| 2 | Return type | Constructor tidak punya return type deklaratif |
| 3 | Otomatis dipanggil | Berjalan ketika instance dibuat |
| 4 | Tidak static | Constructor bukan static method |
| 5 | Default constructor | Disediakan secara implisit jika sesuai kondisi |
| 6 | Initializing formal | Person(this.name, this.age) |
| 7 | Parameter | Bisa positional, named, atau kombinasi |
| 8 | Named constructor | Person.fromJson() |
| 9 | Private constructor | Person._internal() |
| 10 | Inheritance | Constructor tidak diwariskan |
| 11 | Factory | Bisa menentukan object yang dikembalikan |
| 12 | Redirection | Constructor dapat mengarahkan ke constructor lain |
38. Contoh yang menggabungkan banyak konsep
Perhatikan contoh berikut:
class Person {
String name;
int age;
Person(this.name, this.age);
Person.guest()
: this("Guest", 0);
Person.fromName(String name)
: this(name, 0);
void showData() {
print("Name: $name");
print("Age: $age");
}
}
Kita bisa membuat:
Constructor biasa
Person p1 = Person("Sam", 21);
Named constructor
Person p2 = Person.guest();
Named constructor lainnya
Person p3 = Person.fromName("Mark");
Kemudian:
p1.showData();
p2.showData();
p3.showData();
Output:
Name: Sam
Age: 21
Name: Guest
Age: 0
Name: Mark
Age: 0
39. Hubungkan dengan null safety
Ini salah satu alasan constructor sangat penting di Dart.
Cara yang kurang ideal
class Person {
String? name;
int? age;
}
Object bisa berada dalam kondisi:
name = null
age = null
Menggunakan late
class Person {
late String name;
late int age;
}
Sekarang tidak nullable, tetapi harus dipastikan sudah diinisialisasi sebelum dibaca.
Menggunakan constructor
class Person {
String name;
int age;
Person(this.name, this.age);
}
Sekarang:
Person("Sam", 21);
object langsung valid.
Ini biasanya merupakan desain yang lebih aman.
40. Constructor di Flutter
Nah, ini bagian yang sangat penting untuk tujuan kamu belajar Flutter.
Kamu akan sangat sering melihat constructor seperti:
Text(
"Hello",
style: TextStyle(
fontSize: 20,
),
)
atau:
Container(
width: 100,
height: 100,
)
atau:
Padding(
padding: EdgeInsets.all(16),
child: Text("Hello"),
)
Itu semua sangat berkaitan dengan constructor.
Misalnya:
Text("Hello")
secara konsep:
Text
↓
class
Text(...)
↓
constructor invocation
"Hello"
↓
argument
Kemudian named parameter seperti:
Container(
width: 100,
height: 100,
)
membuat kode Flutter mudah dibaca karena kita tahu nilai tersebut digunakan untuk apa.
41. Cara berpikir yang sebaiknya kamu gunakan
Jangan hanya menghafal:
“Constructor adalah special method.”
Lebih bagus pahami alurnya:
CLASS
↓
constructor
↓
membuat/menginisialisasi object
↓
object memiliki state awal yang valid
Misalnya:
Person p = Person("Sam", 21);
bayangkan:
Person class
│
│ constructor
↓
┌─────────────────────┐
│ Person Object │
│ │
│ name = "Sam" │
│ age = 21 │
└─────────────────────┘
↑
│
p
42. Hal-hal dari transkrip yang perlu kamu koreksi
Ada beberapa detail yang sebaiknya jangan kamu hafalkan mentah-mentah.
❌ 1. “Constructor adalah special method”
Boleh untuk pemahaman awal, tetapi secara teknis constructor bukan method biasa.
❌ 2. “Constructor mengembalikan hash code/address object”
Jangan hafalkan seperti itu.
Lebih tepat:
Person p = Person();
ekspresi Person() menghasilkan instance yang kemudian direferensikan oleh p.
hashCode bukan alamat memori object.
❌ 3. “Default constructor selalu ada”
Tidak selalu.
Jika class tidak mendeklarasikan constructor yang sesuai, Dart dapat menyediakan unnamed default constructor secara implisit.
Tetapi ketika kamu sudah mendeklarasikan constructor sendiri, jangan menganggap constructor kosong masih otomatis tersedia.
❌ 4. factory adalah constructor biasa yang boleh memakai return
Lebih tepat:
Factory constructor adalah jenis constructor khusus yang dapat secara eksplisit mengembalikan instance melalui
returndan memiliki kontrol terhadap instance yang dikembalikan.
❌ 5. “Named constructor = overloading”
Bukan overloading.
Dart tidak mendukung traditional constructor overloading.
Named constructor adalah cara Dart menyediakan beberapa constructor dengan nama yang berbeda:
Person();
Person.guest();
Person.fromJson();
43. Cheat sheet constructor
Kalau nanti lupa, gunakan tabel mental ini:
Person()
↓
unnamed/default constructor
Person("Sam", 21)
↓
positional constructor
Person(
name: "Sam",
age: 21,
)
↓
named parameters
Person.fromJson(...)
↓
named constructor
Person._internal()
↓
private constructor
factory Person.fromJson(...)
↓
factory constructor
: this(...)
↓
redirect ke constructor sendiri
: super(...)
↓
memanggil constructor parent
Dan shorthand yang sangat sering digunakan:
class Person {
String name;
int age;
Person(this.name, this.age);
}
44. Kesimpulan
Kalau seluruh video ini diringkas menjadi satu kalimat:
Constructor adalah mekanisme khusus pada Dart yang digunakan saat membuat object agar object tersebut dapat diinisialisasi dengan benar sejak awal.
Kemudian ingat pola ini:
class Person {
String name;
int age;
Person(this.name, this.age);
}
Ketika:
Person p = Person("Sam", 21);
maka:
Person
↓
constructor
↓
object dibuat
↓
name = "Sam"
age = 21
↓
p mereferensikan object tersebut
Dan fitur-fitur yang paling penting untuk kamu kuasai sekarang adalah:
constructor biasa → this.name → positional/named parameter → required → named constructor → private constructor → super() → factory → constructor redirection.
Kalau bagian-bagian ini sudah benar-benar kamu pahami, kamu akan jauh lebih mudah membaca constructor pada widget-widget Flutter, karena Flutter sangat banyak menggunakan constructor dan named parameter.