Soal 1Di class Duck(Swimmer, Flyer):, jika kedua induk mendefinisikan method move, mana yang menang?
Multiple Inheritance dan MRO — Mewarisi dari Lebih dari Satu Induk
Pelajari multiple inheritance di Python. Gabungkan beberapa induk dengan class Anak(A, B):, lihat bagaimana method resolution order (MRO) memilih di antara method bernama sama, dan periksa urutannya dengan __mro__.
Sebelumnya kita membahas pewarisan tunggal, override, dan super(). Python mengizinkan kamu mewarisi dari beberapa induk sekaligus — itu adalah multiple inheritance. Kali ini kita bahas sintaksnya dan aturan yang menentukan induk mana yang dipanggil ketika beberapa punya nama method yang sama: method resolution order (MRO).
Sintaks dasar
Sintaksnya sederhana — daftarkan class induk dipisah koma. Menulis class Duck(Animal, Swimmer, Flyer): berarti Duck mewarisi atribut dan method dari Animal, Swimmer, dan Flyer semuanya.
Di contoh bawah, Animal membawa nama dan perilaku bicara, Swimmer menambah berenang, Flyer menambah terbang — dan Duck membungkus ketiganya menjadi satu makhluk lengkap.
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
pass
class Swimmer:
def swim(self):
return f"{self.name} sedang berenang"
class Flyer:
def fly(self):
return f"{self.name} sedang terbang"
class Duck(Animal, Swimmer, Flyer): # multiple inheritance
def speak(self):
return f"{self.name} bilang kwek"
duck = Duck("Donald")
print(duck.speak()) # Donald bilang kwek
print(duck.swim()) # Donald sedang berenang
print(duck.fly()) # Donald sedang terbang
Duck mewarisi atribut dan __init__ dari Animal, swim dari Swimmer, dan fly dari Flyer. Hanya speak yang di-override oleh Duck sendiri.Method resolution order (MRO) — Induk mana yang menang?
Hal jadi rumit ketika beberapa induk punya method dengan nama sama. Jika Swimmer dan Flyer keduanya mendefinisikan method move, mana yang berjalan ketika kamu memanggil move pada instance Duck?
Python memakai method resolution order (MRO) — urutan pencarian yang tetap — untuk menelusuri class dari atas ke bawah dan menjalankan match pertama. Untuk multiple inheritance, urutannya adalah kiri ke kanan seperti ditulis di class Duck(A, B, C):. Jadi method bernama sama dari A menang; jika tidak ada, dicoba B, lalu C.
class Swimmer:
def move(self):
return "berenang"
class Flyer:
def move(self):
return "terbang"
class Duck(Swimmer, Flyer): # kiri menang = Swimmer.move
pass
class Goose(Flyer, Swimmer): # balik urutan = hasil berbeda
pass
print(Duck().move()) # berenang
print(Goose().move()) # terbang
Duck(Swimmer, Flyer), Python melihat Swimmer dulu, lalu Flyer. Jika keduanya mendefinisikan move, Swimmer.move menang. Susun ulang induk dan hasilnya berubah.Di CPython kamu bisa membaca urutan pencarian sebenarnya dengan NamaClass.__mro__ (runtime di sini adalah MicroPython, yang tidak mengekspos atribut __mro__, jadi snippet di bawah hanya referensi untuk apa yang akan kamu lihat di Python biasa).
# Apa yang akan ditampilkan CPython
class Swimmer:
pass
class Flyer:
pass
class Duck(Swimmer, Flyer):
pass
for cls in Duck.__mro__:
print(cls.__name__)
# Duck
# Swimmer
# Flyer
# object
Apa itu object di akhir?
Setiap class di Python pada akhirnya mewarisi dari class bawaan object. Bahkan saat kamu tidak menulisnya, class Foo: secara internal adalah class Foo(object):. Itulah sebabnya __mro__ selalu berakhir dengan object.
Diamond inheritance dan C3 linearization
Bentuk lain yang muncul adalah diamond inheritance: B dan C masing-masing mewarisi dari A, dan D mewarisi dari keduanya B dan C — menggambar grafik pewarisan menghasilkan bentuk berlian secara harfiah.
A adalah leluhur bersama. B dan C masing-masing mewarisi dari A. D lalu mewarisi dari kedua B dan C — anak panahnya membentuk berlian.Python menghitung MRO dengan algoritma bernama C3 linearization, yang menghasilkan urutan cerdas «coba turunan (B, C) dulu, lalu naik ke leluhur bersama (A) di akhir».
class A:
def method(self):
return "A"
class B(A):
def method(self):
return "B"
class C(A):
def method(self):
return "C"
class D(B, C): # berlian
pass
print(D().method()) # B
Di contoh ini D().method() mengembalikan "B" karena MRO-nya D → B → C → A. Andai B tidak mendefinisikan method, method dari C yang akan jalan; tanpa itu, dari A. «Kiri dulu, tapi leluhur bersama paling akhir» — itulah cheat sheet untuk diamond inheritance.
Memanggil method induk tertentu lewat nama class
Saat kamu khusus ingin memanggil method dari induk tertentu — bukan sekadar yang menang MRO — super() hanya memberi kamu class berikutnya di MRO, jadi kamu cuma bisa memanggil paling banyak satu versi induk. Sebagai gantinya, gunakan ClassInduk.method(self, ...) untuk memilih persis yang kamu mau.
Karena panggilan lewat sisi class, kamu harus meneruskan self sendiri sebagai argumen pertama — satu-satunya keunikan yang perlu diingat.
super() menjalankan hanya satu method (yang berikutnya di MRO). Memanggil dengan nama class seperti A.hello(self) memungkinkan kamu menunjuk induk tertentu terlepas dari MRO — berguna saat kamu mau memanggil beberapa method induk berurutan.class A:
def hello(self):
print("hello dari A")
class B:
def hello(self):
print("hello dari B")
class C(A, B):
def hello(self):
A.hello(self) # panggil hello A secara eksplisit
B.hello(self) # panggil hello B secara eksplisit
print("hello dari C")
C().hello()
# hello dari A
# hello dari B
# hello dari C
Kuat, tapi pakai dengan hemat
Multiple inheritance praktis, tetapi kamu harus menyimpan MRO di kepala terus untuk mengikuti perilakunya — itu biaya kognitif nyata. Dalam praktik, daripada memaksa multiple inheritance, memakai satu induk dan menyimpan class fitur kecil sebagai atribut (composition) sering lebih jelas. Simpan multiple inheritance untuk kasus seperti mencampur kemampuan independen seperti Swimmer / Flyer.
| Yang ingin kamu lakukan | Cara menulisnya |
|---|---|
| Mewarisi banyak induk | class Anak(A, B): ... |
| Lihat induk mana yang menang | NamaClass.__mro__ (CPython) |
| Hanya panggil yang berikut di MRO | super().method(...) |
| Tunjuk induk tertentu | ClassInduk.method(self, ...) |
Cek Pemahaman
Jawab setiap pertanyaan satu per satu.
Soal 2Cara yang benar untuk membaca method resolution order (MRO) suatu class? (CPython)
Soal 3Di multiple inheritance, cara yang benar untuk memanggil method dari induk tertentu dengan nama adalah?