Masukkan Password
52 Super keyword in Dart | Dart super keyword | Dart Tutorial #52
Materi kali ini membahas penggunaan keyword super di Dart. Ini sangat penting karena super akan sering kamu temui ketika belajar inheritance dan Flutter.
Ada dua bentuk utama yang perlu kamu pahami:
super
dan
super(...)
Walaupun sama-sama menggunakan kata super, fungsinya berbeda.
super.member→ mengakses member milik superclass.super(...)→ memanggil constructor superclass.
Saya jelaskan dari dasar supaya tidak tertukar dengan this.
1. Apa itu super?
Misalnya:
class Animal {
int age = 5;
void sound() {
print("Animal sound");
}
}
class Cat extends Animal {
}
Karena:
class Cat extends Animal
maka:
Animal = superclass
Cat = subclass
Di dalam Cat, kita bisa menggunakan:
super
untuk merujuk ke superclass langsung, yaitu Animal.
Secara sederhana:
Animal
↑
│
Cat
Dari dalam Cat:
super
mengarah ke bagian superclass langsungnya, yaitu Animal.
2. Bedakan this dan super
Ini konsep yang sangat penting.
Sebelumnya kita sudah belajar:
this
this mengacu kepada instance/object yang sedang menjalankan method atau constructor tersebut.
Sedangkan:
super
digunakan untuk mengakses bagian superclass langsung dari subclass.
Contoh:
class Animal {
int age = 5;
}
class Cat extends Animal {
void show() {
print(age);
print(super.age);
}
}
Di sini:
age
mencari member berdasarkan konteks Cat.
Sedangkan:
super.age
secara eksplisit mengatakan:
“Saya ingin member
agedari superclass.”
3. Bentuk pertama: super.member
Bentuk pertama adalah:
super.namaMember
Contohnya:
class Animal {
void sound() {
print("Animal sound");
}
}
class Cat extends Animal {
void test() {
super.sound();
}
}
Ketika:
Cat().test();
maka:
Animal sound
Jadi:
super.sound();
berarti:
Panggil method
sound()milik superclass.
4. Kenapa kita membutuhkan super?
Pertanyaan bagus:
“Kalau member superclass bisa diwarisi dan diakses langsung, kenapa perlu
super?”
Jawabannya terutama karena nama member bisa sama atau method bisa di-override.
5. Contoh field superclass dan subclass memiliki nama sama
Misalnya:
class A {
int x = 10;
}
class B extends A {
int x = 20;
void showData() {
print(x);
}
}
Kemudian:
B().showData();
Output:
20
Kenapa bukan 10?
Karena di dalam B, ketika kita menulis:
x
yang dimaksud adalah member x yang berada di B.
Kita bisa membayangkannya:
A
└── x = 10
B extends A
└── x = 20
Sekarang ada dua x:
A.x = 10
B.x = 20
6. Bagaimana mengakses x milik superclass?
Gunakan:
super.x
Contoh:
class A {
int x = 10;
}
class B extends A {
int x = 20;
void showData() {
print(x);
print(super.x);
}
}
Output:
20
10
Jadi:
x
→ B.x
sedangkan:
super.x
→ A.x
7. super juga berguna ketika method di-override
Ini bahkan lebih umum daripada kasus field.
Misalnya:
class Animal {
void sound() {
print("Animal sound");
}
}
class Cat extends Animal {
@override
void sound() {
print("Meow");
}
}
Sekarang:
Cat().sound();
menghasilkan:
Meow
Karena method sound() milik Cat meng-override method Animal.
8. Bagaimana memanggil method superclass yang sudah di-override?
Gunakan:
super.sound();
Contoh:
class Animal {
void sound() {
print("Animal sound");
}
}
class Cat extends Animal {
@override
void sound() {
super.sound();
print("Meow");
}
}
Output:
Animal sound
Meow
Urutannya:
Cat.sound()
↓
super.sound()
↓
Animal.sound()
↓
kembali ke Cat.sound()
↓
print("Meow")
9. Ini pola yang sangat sering digunakan
Misalnya superclass memiliki proses dasar:
class Employee {
void work() {
print("Employee is working");
}
}
Subclass ingin menambahkan perilaku:
class Designer extends Employee {
@override
void work() {
super.work();
print("Designer is designing");
}
}
Output:
Employee is working
Designer is designing
Artinya subclass tidak membuang seluruh perilaku superclass.
Dia berkata:
“Jalankan dulu pekerjaan dasar milik parent, setelah itu tambahkan pekerjaan khusus saya.”
Ini salah satu penggunaan super yang sangat berguna.
10. super hanya mengarah ke immediate superclass
Ini bagian yang sangat penting.
Misalnya:
class A {
int x = 10;
}
class B extends A {
int x = 20;
}
class C extends B {
int x = 30;
}
Strukturnya:
A
↑
B
↑
C
Di dalam C:
x
mengarah ke:
C.x = 30
Sedangkan:
super.x
mengarah ke:
B.x = 20
Bukan A.x.
11. Apakah bisa super.super.x?
Tidak.
Kita tidak bisa melakukan:
super.super.x
Dart tidak menyediakan syntax tersebut.
Jadi dari C, kita punya:
C
│
├── x = 30
│
└── super.x → B.x = 20
Tetapi tidak ada:
super.super.x
untuk langsung mengambil:
A.x = 10
Ini menunjukkan konsep penting:
superhanya merujuk ke immediate superclass, bukan seluruh rantai inheritance.
12. Kenapa super tidak bisa langsung mengakses static member?
Misalnya:
class A {
static int value = 10;
}
Kemudian:
class B extends A {
void show() {
print(super.value);
}
}
Ini tidak valid.
Kenapa?
Karena super digunakan untuk konteks instance, sedangkan static adalah milik class, bukan object.
Untuk static member, gunakan nama class:
print(A.value);
Jadi:
Instance member
→ super.member
Static member
→ ClassName.member
Contoh:
class A {
static int value = 10;
}
class B extends A {
void show() {
print(A.value);
}
}
13. Kenapa super tidak bisa digunakan di static method?
Contoh:
class A {
int x = 10;
}
class B extends A {
static void show() {
print(super.x);
}
}
Ini tidak valid.
Kenapa?
Karena super berkaitan dengan instance context.
Sedangkan static method tidak dijalankan berdasarkan object tertentu.
Misalnya:
B.show();
Tidak ada:
object B tertentu
yang menjadi this.
Karena itu tidak ada konteks instance untuk super.
14. Hubungan this dengan super
Kita bisa membandingkan:
this
↓
current instance/object
sedangkan:
super
↓
immediate superclass
Contoh:
class Parent {
int x = 10;
}
class Child extends Parent {
int x = 20;
void show() {
print(this.x);
print(super.x);
}
}
Output:
20
10
Secara mental:
Child object
│
├── Child.x = 20
│
└── Parent.x = 10
this.x → bagian Child
super.x → bagian superclass langsung.
15. super tidak bisa ditulis di main()
Misalnya:
void main() {
print(super.x);
}
Tidak bisa.
Karena main() bukan instance member dari subclass.
super hanya bermakna dalam konteks subclass yang memiliki superclass langsung.
16. super juga tidak bisa digunakan dalam factory constructor
Misalnya:
class A {
int x = 10;
}
class B extends A {
factory B() {
print(super.x);
return B._internal();
}
B._internal();
}
Ini tidak valid.
Alasannya sama dengan konsep factory yang sudah kita pelajari:
Factory constructor tidak memiliki
thisinstance yang sedang diinisialisasi.
Karena super juga bergantung pada konteks instance, factory constructor tidak dapat menggunakannya seperti generative constructor.
17. Bagian kedua: super(...)
Sekarang kita masuk ke bentuk kedua:
super(...)
Ini berbeda dengan:
super.member
Kalau:
super.x
artinya:
akses member superclass.
Tetapi:
super(...)
artinya:
panggil constructor superclass.
18. Contoh sederhana super()
class A {
A() {
print("Constructor A");
}
}
class B extends A {
B() : super() {
print("Constructor B");
}
}
Kemudian:
B();
Output:
Constructor A
Constructor B
Bagian:
B() : super()
berarti:
Sebelum menjalankan body constructor
B, panggil constructorA().
19. Sebenarnya super() sering tidak perlu ditulis
Kalau superclass mempunyai unnamed zero-parameter constructor:
class A {
A() {
print("A");
}
}
class B extends A {
B() {
print("B");
}
}
Dart secara otomatis dapat melakukan implicit:
super();
Jadi:
B() {
}
secara konsep memiliki pemanggilan superclass default constructor secara implicit.
20. super(...) dengan parameter
Misalnya superclass:
class Person {
String name;
int age;
Person(this.name, this.age);
}
Subclass:
class Employee extends Person {
double salary;
Employee(
String name,
int age,
this.salary,
) : super(name, age);
}
Di sini:
super(name, age)
memanggil:
Person(name, age)
Jadi parameter:
Employee
│
├── name
├── age
└── salary
diteruskan:
name ──→ Person.name
age ──→ Person.age
salary ──→ Employee.salary
21. super bisa memanggil named constructor
Misalnya:
class Person {
Person(this.name);
Person.guest()
: name = "Guest";
String name;
}
Subclass:
class Employee extends Person {
Employee.guest() : super.guest();
}
Perhatikan:
super.guest()
Artinya:
Panggil named constructor
guestmilik superclass.
Jadi:
super()
→ Person()
super.guest()
→ Person.guest()
22. super constructor call selalu menuju superclass langsung
Misalnya:
class A {
A() {
print("A");
}
}
class B extends A {
B() : super() {
print("B");
}
}
class C extends B {
C() : super() {
print("C");
}
}
Kalau:
C();
alur:
C()
↓
B()
↓
A()
Bukan:
C()
↓
super.super()
↓
A()
Setiap class hanya menggunakan super untuk superclass langsung.
23. Bedakan super dan super(...)
Ini wajib kamu kuasai.
| Syntax | Fungsi |
|---|---|
super | referensi ke superclass langsung |
super.x | akses field/member superclass |
super.method() | panggil method superclass |
super() | panggil unnamed constructor superclass |
super(10) | panggil unnamed constructor superclass dengan parameter |
super.named() | panggil named constructor superclass |
Contoh:
super.x;
berarti:
Ambil
xdari superclass.
Sedangkan:
super(10);
berarti:
Panggil constructor superclass dengan
10.
24. Jangan tertukar dengan this(...)
Kita sebelumnya sudah belajar constructor redirection.
Ada:
this(...)
dan:
super(...)
Perbedaannya:
this(...)
↓
constructor lain dalam class yang sama
sedangkan:
super(...)
↓
constructor superclass
Contoh:
class A {
A() {}
}
class B extends A {
B() : super();
B.demo() : this();
}
B():
B()
↓
A()
Sedangkan B.demo():
B.demo()
↓
B()
↓
A()
25. Kenapa constructor superclass dipanggil sebelum subclass?
Bayangkan:
class Person {
String name;
int age;
Person(this.name, this.age);
}
Kemudian:
class Employee extends Person {
double salary;
Employee(
String name,
int age,
this.salary,
) : super(name, age);
}
Object Employee membutuhkan bagian:
Person
├── name
└── age
Employee
└── salary
Maka bagian Person harus diinisialisasi sebagai bagian dari proses pembuatan Employee.
Itulah mengapa constructor superclass dipanggil terlebih dahulu.
26. Hubungkan dengan overriding
super sangat erat dengan materi sebelumnya tentang overriding.
Misalnya:
class Animal {
void sound() {
print("Animal sound");
}
}
class Dog extends Animal {
@override
void sound() {
print("Woof");
}
}
Kalau:
Dog().sound();
hasil:
Woof
Tetapi:
class Dog extends Animal {
@override
void sound() {
super.sound();
print("Woof");
}
}
hasil:
Animal sound
Woof
Jadi:
@override
dan:
super.method()
sering digunakan bersama.
@override:
“Saya membuat implementasi baru.”
super.method():
“Saya tetap ingin menjalankan implementasi superclass.”
27. Contoh dunia nyata
Bayangkan:
class Vehicle {
void start() {
print("Vehicle engine starts");
}
}
class Car extends Vehicle {
@override
void start() {
super.start();
print("Car air conditioner starts");
}
}
Ketika:
Car().start();
hasil:
Vehicle engine starts
Car air conditioner starts
Secara konsep:
Vehicle
│
└── start()
↓
dasar
Car
│
└── start()
↓
super.start()
↓
jalankan dasar Vehicle
↓
tambahkan perilaku Car
Ini sangat berguna ketika subclass ingin memperluas behavior, bukan sepenuhnya menggantikannya.
28. Koreksi kecil dari transcript: “super adalah reference ke superclass object”
Untuk pemahaman pemula, transcript menggunakan istilah:
“super adalah reference yang merujuk ke superclass object.”
Ini agak berbahaya kalau dipahami terlalu literal.
Lebih aman mengatakan:
superadalah keyword yang memberikan akses ke member atau constructor superclass langsung dari subclass.
Jangan membayangkan bahwa ada object kedua yang bisa kita pegang dengan:
super → object parent
seperti pointer mentah.
Dart mengabstraksikan detail object/reference tersebut.
Yang penting adalah akses ke behavior/member superclass.
29. Koreksi lain: field overriding
Transcript memberikan contoh:
class A {
int x = 10;
}
class B extends A {
int x = 20;
}
Ini bagus untuk menjelaskan shadowing/hiding field, tetapi jangan menyamakan perilakunya dengan method overriding.
Dalam Dart, field memiliki aturan yang berbeda dari method dan analyzer dapat memberikan rekomendasi terkait deklarasi field dengan nama yang sama.
Untuk belajar super, contoh field tersebut boleh digunakan:
x
versus:
super.x
Tetapi untuk konsep polymorphism dan overriding, lebih baik fokus pada method:
@override
void sound() {}
30. Contoh lengkap: field + method + constructor
Sekarang kita gabungkan semuanya.
class Person {
String name;
int age;
Person(this.name, this.age);
void show() {
print("Person: $name, $age");
}
}
class Employee extends Person {
double salary;
Employee(
String name,
int age,
this.salary,
) : super(name, age);
@override
void show() {
super.show();
print("Salary: $salary");
}
}
Kemudian:
void main() {
Employee employee = Employee(
"Sam",
21,
25000,
);
employee.show();
}
Output:
Person: Sam, 21
Salary: 25000
Ada dua penggunaan super di sini.
Pertama:
super(name, age)
→ memanggil constructor Person.
Kedua:
super.show()
→ memanggil method show() milik Person.
31. Cara membaca kode super
Setiap kali kamu melihat super, tanyakan:
Apakah ada tanda kurung setelah super?
Kalau:
super(...)
berarti:
constructor superclass
Kalau:
super.nama
atau:
super.namaMethod()
berarti:
member superclass
Contoh:
super(name, age)
→ constructor.
super.name
→ field/property.
super.show()
→ method.
32. Ringkasan aturan super
super bisa digunakan untuk:
super.field
mengakses field/member superclass.
super.method()
memanggil method superclass.
super(...)
memanggil generative constructor superclass.
super tidak bisa digunakan untuk:
❌ static method:
static void test() {
super.x;
}
❌ factory constructor:
factory B() {
super.x;
}
❌ main():
void main() {
super.x;
}
❌ mengakses superclass dua tingkat sekaligus:
super.super.x
❌ mengubah super:
super = something;
super bukan variabel yang bisa diberi nilai.
33. Cheat sheet paling penting
Simpan tabel ini di kepala:
this
↓
object/current instance
super
↓
immediate superclass
Kemudian:
this.name
→ name milik object/current class
super.name
→ name dari superclass
this()
→ constructor lain di class yang sama
super()
→ constructor superclass
this.named()
→ named constructor di class sendiri
super.named()
→ named constructor superclass
Dan:
@override
→ subclass mengganti implementation superclass
super.method()
→ subclass tetap memanggil implementation superclass
34. Mental model terakhir
Bayangkan inheritance seperti ini:
Animal
│
┌────┴────┐
│ │
Cat Dog
Di dalam Cat:
super
berarti:
Animal
Kalau:
super.sound();
berarti:
"Animal, jalankan sound() milikmu."
Kalau:
super();
di constructor:
"Animal, jalankan constructor-mu."
Kalau inheritance lebih panjang:
Object
↓
Animal
↓
Cat
dari Cat:
super
hanya menuju:
Animal
bukan langsung:
Object
Kesimpulan
Jadi sebenarnya materi ini bisa disederhanakan menjadi dua fungsi besar super:
1. Mengakses member superclass
super.x;
super.show();
super.calculate();
Dipakai terutama ketika subclass melakukan overriding atau memiliki member dengan nama yang sama.
2. Memanggil constructor superclass
B() : super();
B(int x) : super(x);
B.demo() : super.named();
Dipakai untuk menentukan constructor superclass yang harus dijalankan.
Kalau kamu menemukan kode Flutter seperti:
const MyWidget({super.key});
itu juga berkaitan dengan konsep constructor superclass yang kita bahas—key diteruskan ke constructor superclass. Jadi pemahaman super ini akan sangat membantu ketika mulai membaca constructor widget Flutter yang lebih kompleks.