Masukkan Password
50 Method overriding in Dart | Polymorphism in Dart | Dart Tutorial #50
Pada materi ini kita masuk ke dua konsep yang sangat penting dalam OOP (Object-Oriented Programming), yaitu:
- Method Overriding
- Polymorphism
Keduanya sangat erat hubungannya dengan inheritance yang sudah kita bahas sebelumnya.
Saya akan jelaskan dari dasar, lalu kita bedah contoh kodenya, termasuk beberapa bagian transcript yang kurang tepat secara teknis.
1. Gambaran besar
Sebelum masuk ke kode, pahami hubungan ketiga konsep ini:
Inheritance
↓
Subclass mendapatkan kemampuan dari superclass
↓
Method Overriding
↓
Subclass mengganti implementasi method milik superclass
↓
Polymorphism
↓
Method yang dipanggil dapat berbeda tergantung object sebenarnya
Contoh sederhananya:
Clock
↑
|
DigitalClock
DigitalClock adalah turunan dari Clock.
Clock mempunyai:
void run() {
print("Clock is running");
}
Kemudian DigitalClock mengganti perilaku run():
@override
void run() {
print("Digital clock is running");
}
Nah, penggantian method tersebut disebut method overriding.
Kemudian ketika kita mempunyai:
Clock clock = DigitalClock();
clock.run();
yang dipanggil ternyata:
Digital clock is running
bukan:
Clock is running
Ini yang membawa kita ke konsep runtime polymorphism.
2. Apa itu Method Overriding?
Mari kita mulai dari inheritance sederhana.
class Clock {
void run() {
print("Clock is running");
}
}
Kita mempunyai class Clock.
Class tersebut memiliki method:
run()
Sekarang kita buat subclass:
class DigitalClock extends Clock {
}
Karena:
class DigitalClock extends Clock
maka DigitalClock mewarisi member yang dapat diwariskan dari Clock.
Jadi meskipun kita tidak menulis run() di dalam DigitalClock, kita tetap bisa:
void main() {
DigitalClock clock = DigitalClock();
clock.run();
}
Output:
Clock is running
Karena run() berasal dari superclass Clock.
3. Bagaimana kalau DigitalClock ingin memiliki perilaku berbeda?
Misalnya kita ingin:
Clock → Clock is running
DigitalClock → Digital clock is running
Kita bisa menulis ulang method run() di subclass:
class DigitalClock extends Clock {
@override
void run() {
print("Digital clock is running");
}
}
Sekarang DigitalClock mempunyai implementasi run() sendiri.
Inilah yang disebut:
Method overriding adalah ketika subclass menyediakan implementasi baru untuk method yang diwarisi dari superclass.
4. Kenapa disebut “overriding”?
Kata override bisa kita pahami sebagai:
“Menggantikan perilaku yang sebelumnya sudah ada.”
Misalnya superclass mengatakan:
void run() {
print("Clock is running");
}
Subclass mengatakan:
@override
void run() {
print("Digital clock is running");
}
Artinya:
Clock
└── run()
↓
"Clock is running"
DigitalClock
└── run()
↓
"Digital clock is running"
Method-nya bernama sama, tetapi implementasinya berbeda.
5. Apa syarat overriding?
Secara sederhana, subclass harus membuat method yang kompatibel dengan method superclass.
Contoh:
class Clock {
void run() {
print("Clock is running");
}
}
class DigitalClock extends Clock {
@override
void run() {
print("Digital clock is running");
}
}
Perhatikan:
Superclass
void run()
Subclass
void run()
Nama method sama:
run
Parameter sama:
tidak ada parameter
Return type kompatibel:
void
Jadi subclass benar-benar meng-override method superclass.
6. Apa fungsi @override?
Kita biasanya menulis:
@override
void run() {
print("Digital clock is running");
}
@override disebut annotation.
Fungsinya memberi tahu programmer dan analyzer Dart:
“Method ini dimaksudkan untuk meng-override method dari superclass.”
Jadi ini:
@override
void run() {}
membantu kita memahami bahwa run() bukan sekadar method baru milik DigitalClock.
Kenapa sebaiknya menggunakan @override?
Misalnya kita salah ketik:
class Clock {
void run() {
print("Clock is running");
}
}
class DigitalClock extends Clock {
@override
void rn() {
print("Digital clock is running");
}
}
Kita bermaksud menulis run, tetapi malah menulis rn.
Karena ada:
@override
Dart akan memberi tahu bahwa tidak ada method superclass yang sedang di-override.
Jadi @override juga membantu mendeteksi kesalahan.
7. Apa yang terjadi jika subclass tidak melakukan overriding?
Contohnya:
class Clock {
void run() {
print("Clock is running");
}
}
class DigitalClock extends Clock {
}
Kemudian:
DigitalClock clock = DigitalClock();
clock.run();
Output:
Clock is running
Kenapa?
Karena DigitalClock tidak memiliki implementasi run() sendiri.
Maka method yang diwarisi dari Clock digunakan.
8. Kalau subclass melakukan overriding?
Sekarang:
class Clock {
void run() {
print("Clock is running");
}
}
class DigitalClock extends Clock {
@override
void run() {
print("Digital clock is running");
}
}
Kemudian:
DigitalClock clock = DigitalClock();
clock.run();
Output:
Digital clock is running
Karena object yang digunakan adalah object DigitalClock.
9. Superclass object vs subclass object
Ini penting sekali.
Misalnya:
class Clock {
void run() {
print("Clock is running");
}
}
class DigitalClock extends Clock {
@override
void run() {
print("Digital clock is running");
}
}
Kemudian:
Clock clock1 = Clock();
DigitalClock clock2 = DigitalClock();
clock1.run();
clock2.run();
Output:
Clock is running
Digital clock is running
Karena:
clock1 → object Clock
clock2 → object DigitalClock
Maka masing-masing menggunakan implementasi yang sesuai dengan object tersebut.
10. Kenapa subclass melakukan overriding?
Ada dua alasan utama.
Alasan 1 — Subclass membutuhkan perilaku yang berbeda
Misalnya:
class Animal {
void sound() {
print("Animal makes sound");
}
}
Kemudian:
class Cat extends Animal {
@override
void sound() {
print("Meow");
}
}
Dan:
class Dog extends Animal {
@override
void sound() {
print("Woof");
}
}
Sekarang:
Animal
↑
├── Cat
└── Dog
Masing-masing memiliki perilaku berbeda.
Cat().sound();
Dog().sound();
Output:
Meow
Woof
Padahal method-nya sama-sama:
sound()
Tetapi implementasinya berbeda.
11. Alasan 2 — Mempertahankan behavior lama + menambahkan behavior baru
Ini juga sangat penting.
Misalnya superclass:
class Clock {
void run() {
print("Clock is running");
}
}
Subclass:
class DigitalClock extends Clock {
@override
void run() {
super.run();
print("Digital clock is running");
}
}
Kemudian:
DigitalClock clock = DigitalClock();
clock.run();
Output:
Clock is running
Digital clock is running
Apa yang terjadi?
Pertama:
super.run();
memanggil method run() milik superclass.
Setelah itu:
print("Digital clock is running");
dijalankan.
Jadi:
Superclass behavior
+
Subclass additional behavior
12. Apa itu super.run()?
Kalau:
this.run()
berhubungan dengan object saat ini, maka:
super.run()
digunakan untuk mengakses implementasi dari superclass.
Misalnya:
class Clock {
void run() {
print("Clock is running");
}
}
class DigitalClock extends Clock {
@override
void run() {
super.run();
print("Digital clock is running");
}
}
Ketika:
DigitalClock().run();
yang terjadi:
DigitalClock.run()
↓
super.run()
↓
Clock.run()
↓
"Clock is running"
↓
kembali ke DigitalClock.run()
↓
"Digital clock is running"
13. Istilah penting: overridden vs overriding method
Ada dua istilah yang sering membingungkan.
Misalnya:
class Clock {
void run() {
print("Clock is running");
}
}
class DigitalClock extends Clock {
@override
void run() {
print("Digital clock is running");
}
}
Method di superclass:
Clock.run()
disebut overridden method.
Method di subclass:
DigitalClock.run()
disebut overriding method.
Cara mengingatnya:
Superclass
↓
method lama
↓
OVERRIDDEN
Subclass
↓
method baru yang menggantikan
↓
OVERRIDING
14. Sekarang masuk ke Polymorphism
Sekarang kita masuk konsep yang lebih besar.
Polymorphism berasal dari bahasa Yunani:
poly = banyak
morph = bentuk
Jadi secara sederhana:
Polymorphism = satu bentuk/interface dapat digunakan untuk menghasilkan perilaku yang berbeda.
Dalam OOP, salah satu bentuk paling penting adalah:
Satu reference superclass dapat menunjuk ke object subclass, dan pemanggilan method yang di-override akan menggunakan implementasi sesuai object sebenarnya.
Ini agak sulit di awal, jadi kita pelan-pelan.
15. Reference dan object itu berbeda
Perhatikan:
Clock clock = DigitalClock();
Ini sangat penting.
Ada dua bagian:
Clock
dan:
DigitalClock()
Clock
adalah tipe reference.
DigitalClock()
adalah object yang sebenarnya dibuat.
Gambaran sederhananya:
Clock clock
|
| menunjuk ke
↓
DigitalClock object
Jadi reference-nya bertipe Clock, tetapi object-nya adalah DigitalClock.
16. Kenapa ini diperbolehkan?
Karena:
DigitalClock is a Clock
atau:
DigitalClock adalah sebuah Clock.
Karena:
class DigitalClock extends Clock
maka object DigitalClock dapat diperlakukan sebagai Clock.
Contoh:
Clock clock = DigitalClock();
Ini valid.
Tetapi kebalikannya:
DigitalClock clock = Clock();
tidak valid.
Karena:
Clock belum tentu DigitalClock
Analogi:
Animal
↑
Dog
Semua Dog adalah Animal.
Tetapi tidak semua Animal adalah Dog.
Jadi:
Animal animal = Dog(); // ✅
Dog dog = Animal(); // ❌
17. Contoh runtime polymorphism
Sekarang lihat contoh paling penting:
class Clock {
void run() {
print("Clock is running");
}
}
class DigitalClock extends Clock {
@override
void run() {
print("Digital clock is running");
}
}
Kemudian:
void main() {
Clock clock = Clock();
clock.run();
clock = DigitalClock();
clock.run();
}
Output:
Clock is running
Digital clock is running
Perhatikan sesuatu yang menarik.
Reference-nya tetap:
clock
Pemanggilan method-nya juga tetap:
clock.run();
Tetapi hasilnya berbeda.
18. Kenapa hasilnya berbeda?
Karena object yang ditunjuk oleh clock berbeda.
Pertama:
Clock clock = Clock();
Gambarnya:
clock
↓
Clock object
Ketika:
clock.run();
yang digunakan:
Clock.run()
Output:
Clock is running
Kemudian:
clock = DigitalClock();
Sekarang:
clock
↓
DigitalClock object
Ketika:
clock.run();
Dart menemukan bahwa object sebenarnya adalah DigitalClock.
Karena DigitalClock melakukan overriding terhadap run(), maka:
DigitalClock.run()
yang dijalankan.
Output:
Digital clock is running
19. Inilah Runtime Polymorphism
Disebut runtime polymorphism karena method yang benar dipilih berdasarkan object sebenarnya saat program berjalan.
Secara sederhana:
Reference
↓
object sebenarnya
↓
method yang di-override
↓
dijalankan
Jadi:
Clock clock = DigitalClock();
clock.run();
Reference:
Clock
Object:
DigitalClock
Method:
DigitalClock.run()
20. Ini bukan berarti compiler tidak tahu apa-apa
Ada sedikit penyederhanaan dalam transcript yang perlu diluruskan.
Transcript mengatakan kira-kira:
“Method mana yang dipanggil tidak diputuskan saat compile time, tetapi saat runtime.”
Sebagai penjelasan pemula, ini boleh dipahami seperti itu.
Tetapi jangan diartikan bahwa compiler tidak melakukan pengecekan.
Compiler tetap tahu bahwa:
Clock clock
hanya menjamin API yang tersedia dari Clock.
Misalnya:
class Clock {
void run() {}
}
class DigitalClock extends Clock {
void displayDigitalTime() {}
}
Kalau:
Clock clock = DigitalClock();
clock.run(); // ✅
tetapi:
clock.displayDigitalTime(); // ❌
mengapa?
Karena tipe reference-nya:
Clock
dan Clock tidak mempunyai displayDigitalTime().
Jadi ada dua hal:
Compile time
Dart mengecek:
“Apakah method ini tersedia pada tipe reference?”
Runtime
Untuk overridden method, Dart menentukan implementasi instance yang sesuai dengan object sebenarnya.
21. Contoh yang lebih nyata: Animal
Contoh Clock bagus untuk memahami konsep, tetapi Animal biasanya lebih mudah dipahami.
class Animal {
void sound() {
print("Animal makes sound");
}
}
Kemudian:
class Cat extends Animal {
@override
void sound() {
print("Meow");
}
}
Dan:
class Dog extends Animal {
@override
void sound() {
print("Woof");
}
}
Sekarang kita bisa:
void main() {
Animal animal;
animal = Cat();
animal.sound();
animal = Dog();
animal.sound();
}
Output:
Meow
Woof
Perhatikan:
animal.sound();
tetap sama.
Tetapi:
animal = Cat()
menghasilkan:
Meow
sedangkan:
animal = Dog()
menghasilkan:
Woof
Inilah polymorphism.
22. Analogi manusia
Bayangkan kita mempunyai:
Animal
dan method:
sound()
Kita tidak perlu tahu secara detail hewan apa yang kita hadapi.
Kita hanya mengatakan:
“Animal, keluarkan suara.”
Kalau ternyata object-nya:
Cat
maka:
Meow
Kalau:
Dog
maka:
Woof
Kalau:
Cow
mungkin:
Moo
Jadi interface yang kita gunakan sama:
sound()
tetapi perilakunya berbeda.
23. Hubungan Inheritance → Overriding → Polymorphism
Sekarang kita gabungkan.
Tahap 1 — Inheritance
class Cat extends Animal
Cat mewarisi Animal.
↓
Tahap 2 — Overriding
@override
void sound() {
print("Meow");
}
Cat mengubah perilaku sound().
↓
Tahap 3 — Polymorphism
Animal animal = Cat();
animal.sound();
Reference bertipe Animal, tetapi object sebenarnya Cat.
↓
Output:
Meow
Jadi ketiganya sangat berkaitan:
Inheritance
↓
memungkinkan subclass
↓
Method Overriding
↓
subclass punya implementasi berbeda
↓
Polymorphism
↓
reference superclass dapat bekerja
dengan berbagai subclass
24. Polymorphism sangat berguna untuk membuat kode fleksibel
Misalnya kita mempunyai:
class Animal {
void sound() {
print("Animal sound");
}
}
class Cat extends Animal {
@override
void sound() {
print("Meow");
}
}
class Dog extends Animal {
@override
void sound() {
print("Woof");
}
}
Kita bisa membuat function:
void makeSound(Animal animal) {
animal.sound();
}
Kemudian:
makeSound(Cat());
makeSound(Dog());
Output:
Meow
Woof
Function makeSound() tidak perlu tahu apakah object tersebut:
Cat
Dog
Cow
Bird
Yang penting object tersebut adalah:
Animal
dan mempunyai:
sound()
Ini salah satu kekuatan terbesar polymorphism.
25. Contoh yang sangat relevan dengan Flutter
Inheritance dan overriding sangat penting dalam Flutter.
Misalnya kita membuat widget:
class MyWidget extends StatelessWidget {
const MyWidget({super.key});
@override
Widget build(BuildContext context) {
return Text("Hello");
}
}
Perhatikan:
class MyWidget extends StatelessWidget
Artinya:
MyWidget
↓ extends
StatelessWidget
Kemudian kita menulis:
@override
Widget build(BuildContext context)
Kita mengimplementasikan/meng-override perilaku build() untuk widget kita.
Jadi ketika Flutter membutuhkan widget tersebut untuk dibangun, implementasi build() dari MyWidget digunakan.
Ini menunjukkan kenapa konsep inheritance dan overriding bukan sekadar teori.
26. Contoh lain di Flutter
Misalnya:
class MyPage extends StatelessWidget {
const MyPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text("Hello"),
),
);
}
}
Ada dua konsep penting:
extends StatelessWidget
→ inheritance.
Kemudian:
@override
Widget build(...)
→ overriding.
Jadi ketika belajar Flutter, kamu akan sangat sering bertemu dengan konsep ini.
27. Compile-time polymorphism vs Runtime polymorphism
Transcript juga membahas dua jenis polymorphism.
Secara umum:
Polymorphism
├── Compile-time
└── Runtime
Namun di bagian ini kita harus hati-hati karena transcript menggunakan contoh dari Java/C++.
A. Compile-time polymorphism
Biasanya konsep ini dikaitkan dengan method overloading.
Contohnya di bahasa tertentu:
add(int, int)
add(double, double)
add(int, int, int)
Compiler menentukan method mana yang digunakan berdasarkan signature argument.
Tetapi Dart tidak mendukung method overloading tradisional seperti Java/C++.
Misalnya kamu tidak bisa melakukan:
class Calculator {
int add(int a, int b) => a + b;
double add(double a, double b) => a + b; // ❌
}
Jadi jangan menganggap Dart mempunyai method overloading tradisional.
28. Dart punya cara lain untuk membuat API fleksibel
Dart menyediakan:
- optional positional parameters
- named parameters
- default values
- generics
- extension methods
- dan mekanisme lainnya
Misalnya:
void greet(String name, [String? message]) {
print(message ?? "Hello $name");
}
Kita bisa:
greet("Budi");
atau:
greet("Budi", "Good morning");
Tetapi ini bukan method overloading tradisional.
29. Runtime polymorphism adalah bagian yang sangat penting di Dart
Contohnya:
class Animal {
void sound() {
print("Animal sound");
}
}
class Cat extends Animal {
@override
void sound() {
print("Meow");
}
}
Kemudian:
Animal animal = Cat();
animal.sound();
Output:
Meow
Ini adalah contoh runtime polymorphism melalui inheritance + overriding.
30. Jangan salah memahami “object memiliki banyak bentuk”
Definisi:
Polymorphism adalah kemampuan object untuk memiliki banyak bentuk.
Ini benar sebagai gambaran umum, tetapi untuk pemula kalimat ini sering membingungkan.
Lebih mudah kalau kita pahami sebagai:
Satu reference dapat digunakan untuk menangani berbagai object yang masih berada dalam hubungan inheritance, sementara perilaku method dapat berbeda sesuai object sebenarnya.
Misalnya:
Animal animal;
animal bisa menunjuk ke:
animal = Cat();
atau:
animal = Dog();
atau:
animal = Cow();
Selama semuanya:
Animal
↑
┌─┼─┐
Cat Dog Cow
31. Bedakan “tipe reference” dan “tipe object”
Ini salah satu hal yang sangat penting untuk dikuasai.
Perhatikan:
Animal animal = Cat();
Ada dua perspektif.
Dari sisi reference
Animal
Artinya Dart hanya menjamin kemampuan yang tersedia pada Animal.
Dari sisi object
Cat
Artinya object yang sebenarnya adalah Cat.
Jadi:
Reference type
↓
Animal
|
↓
Actual object
↓
Cat
Karena Cat melakukan override:
sound()
maka:
animal.sound();
menjalankan:
Cat.sound()
32. Contoh dengan tiga subclass
Ini contoh yang sangat bagus untuk memahami polymorphism:
class Animal {
void sound() {
print("Animal sound");
}
}
class Cat extends Animal {
@override
void sound() {
print("Meow");
}
}
class Dog extends Animal {
@override
void sound() {
print("Woof");
}
}
class Cow extends Animal {
@override
void sound() {
print("Moo");
}
}
Sekarang:
void makeSound(Animal animal) {
animal.sound();
}
Kita bisa:
makeSound(Cat());
makeSound(Dog());
makeSound(Cow());
Output:
Meow
Woof
Moo
Function-nya cuma satu:
makeSound(Animal animal)
Tetapi bisa menangani berbagai object.
Itulah manfaat polymorphism.
33. Kenapa tidak membuat function berbeda-beda?
Tanpa polymorphism mungkin kita tergoda membuat:
void makeCatSound(Cat cat) {
cat.sound();
}
void makeDogSound(Dog dog) {
dog.sound();
}
void makeCowSound(Cow cow) {
cow.sound();
}
Ini membuat kode lebih banyak.
Dengan polymorphism:
void makeSound(Animal animal) {
animal.sound();
}
Satu function bisa menangani semuanya.
Ini membuat program lebih:
- fleksibel
- mudah dikembangkan
- mengurangi ketergantungan pada class tertentu
- lebih mudah dipelihara
34. Contoh: menambahkan subclass baru
Misalnya nanti kita tambahkan:
class Bird extends Animal {
@override
void sound() {
print("Tweet");
}
}
Function ini:
void makeSound(Animal animal) {
animal.sound();
}
tidak perlu diubah.
Kita cukup:
makeSound(Bird());
Output:
Tweet
Inilah salah satu manfaat besar desain polymorphic.
35. super dan override jangan tertukar
Perhatikan:
@override
void run() {
super.run();
print("Digital clock is running");
}
Ada dua konsep berbeda.
@override
Memberi tahu bahwa kita sedang mengganti implementasi superclass.
super.run()
Memanggil implementasi run() milik superclass.
Jadi:
@override
↓
"Saya mengganti method parent."
super.run()
↓
"Saya ingin menjalankan method parent."
36. Analogi gampang
Bayangkan ada aturan perusahaan:
Employee
↓
work()
Default:
Employee bekerja
Kemudian ada:
Programmer extends Employee
Programmer meng-override:
@override
void work() {
print("Programmer writes code");
}
Ada juga:
Designer extends Employee
yang meng-override:
@override
void work() {
print("Designer creates design");
}
Sekarang:
void doWork(Employee employee) {
employee.work();
}
Kita bisa:
doWork(Programmer());
doWork(Designer());
Hasil:
Programmer writes code
Designer creates design
Function doWork() tidak perlu tahu detail object-nya.
Itulah polymorphism.
37. Koreksi beberapa bagian transcript
Ada beberapa istilah dalam transcript yang kemungkinan berasal dari speech-to-text atau penyederhanaan.
1. “Method overwriting”
Istilah yang benar:
Method overriding
Bukan overwriting.
2. “Same return type, method name, parameter list”
Sebagai pemahaman dasar boleh digunakan, tetapi secara teknis aturan overriding Dart lebih luas daripada sekadar mengatakan semuanya harus identik. Yang penting signature/tipe method harus kompatibel dengan method yang dioverride.
Untuk level awal, ingat:
nama method sama
parameter kompatibel
return type kompatibel
3. “Object memiliki banyak bentuk”
Jangan membayangkan object benar-benar berubah bentuk secara fisik.
Lebih tepat:
satu reference
↓
dapat merujuk ke object-object dari
subclass yang berbeda
dan method yang dioverride berperilaku sesuai object sebenarnya.
4. Compile-time polymorphism
Transcript menghubungkan compile-time polymorphism dengan method overloading.
Itu umum dalam pembahasan OOP, tetapi Dart tidak mempunyai method overloading tradisional seperti Java/C++.
Jadi jangan mencoba membuat:
void test(int x) {}
void test(String x) {} // ❌
di Dart.
5. super.run()
super.run() bukan overriding.
Justru:
@override
→ membuat/mendefinisikan overriding method.
Sedangkan:
super.run()
→ memanggil implementasi superclass.
38. Perbedaan Overriding dan Polymorphism
Ini sangat penting.
| Konsep | Artinya |
|---|---|
| Inheritance | Class mewarisi class lain |
| Overriding | Subclass mengganti implementasi method superclass |
| Polymorphism | Satu interface/reference dapat menangani berbagai bentuk object |
@override | Annotation untuk menandai overriding |
super.method() | Memanggil implementasi superclass |
Hubungannya:
Inheritance
↓
Subclass mendapatkan method
↓
Subclass bisa melakukan overriding
↓
Object subclass dapat diperlakukan sebagai superclass
↓
Polymorphism
39. Perhatikan contoh ini baik-baik
class Animal {
void sound() {
print("Animal sound");
}
}
class Cat extends Animal {
@override
void sound() {
print("Meow");
}
}
void main() {
Animal animal = Cat();
animal.sound();
}
Mari kita baca satu per satu.
Baris 1
class Animal
Membuat superclass.
Baris 2
void sound()
Animal mempunyai method sound().
Baris 3
class Cat extends Animal
Cat mewarisi Animal.
Baris 4
@override
Kita akan mengganti implementasi sound() milik Animal.
Baris berikutnya
void sound() {
print("Meow");
}
Cat memiliki implementasi sound() sendiri.
Kemudian:
Animal animal = Cat();
Reference:
Animal
Object:
Cat
Kemudian:
animal.sound();
Karena object sebenarnya adalah Cat, maka:
Cat.sound()
yang dijalankan.
Output:
Meow
40. Gambaran visual keseluruhan
Kalau dibuat seperti diagram:
Animal
|
sound()
|
┌───────────┴───────────┐
↓ ↓
Cat Dog
| |
@override @override
sound() sound()
| |
Meow Woof
Kemudian:
Animal animal;
Reference animal dapat menunjuk ke:
animal → Cat
atau:
animal → Dog
Pemanggilannya tetap:
animal.sound();
Tetapi hasilnya:
Cat → Meow
Dog → Woof
Itulah inti polymorphism.
41. Ringkasan paling penting
Kalau dari seluruh materi ini kamu hanya ingin mengingat beberapa hal, ingat ini:
1. Inheritance
class Cat extends Animal
Artinya:
Cat adalah Animal.
2. Method overriding
class Cat extends Animal {
@override
void sound() {
print("Meow");
}
}
Artinya:
Cat mengganti implementasi
sound()milik Animal.
3. @override
@override
Artinya:
Method ini dimaksudkan untuk meng-override method dari superclass.
4. super
super.sound();
Artinya:
Jalankan implementasi
sound()dari superclass.
5. Polymorphism
Animal animal = Cat();
animal.sound();
Reference:
Animal
Object sebenarnya:
Cat
Method yang dijalankan:
Cat.sound()
42. Cara menghafalnya
Gunakan kalimat sederhana ini:
Inheritance = mewarisi. Overriding = mengganti perilaku yang diwarisi. Polymorphism = satu interface/reference bisa bekerja dengan berbagai object dan menghasilkan perilaku sesuai object tersebut.
Atau:
EXTENDS
↓
mewarisi
@override
↓
mengganti perilaku
super
↓
memanggil perilaku parent
polymorphism
↓
perilaku berbeda melalui interface/reference yang sama
Dan untuk Flutter:
class MyPage extends StatelessWidget {
const MyPage({super.key});
@override
Widget build(BuildContext context) {
return const Text("Hello");
}
}
Di sini kamu sudah melihat konsep-konsep yang dipelajari:
extends StatelessWidget
↓
inheritance
@override
↓
method overriding
build()
↓
perilaku subclass
Jadi method overriding dan polymorphism bukan materi yang berdiri sendiri. Keduanya merupakan kelanjutan langsung dari inheritance, dan pemahaman ketiganya akan sangat membantu ketika mulai membaca kode Flutter yang lebih kompleks.