Fungsi super() sudah tiga chapter menjadi bintang tanpa pernah dibedah utuh: memperbaiki __init__ di Chapter Inheritance, dikejutkan oleh MRO di Chapter Method Resolution Order. Saatnya memberinya panggung sendiri. super() adalah cara class anak memanggil perilaku dari class berikutnya dalam MRO — tanpa harus menuliskan nama class itu secara manual. Dua manfaat langsungnya: kode anak tidak terikat kaku pada nama induk (mengganti nama induk tidak merusak anak), dan panggilan-panggilan super() bisa bekerja sama membentuk rantai yang adil di hierarki berlian. Chapter ini membedah pola-pola pemakaiannya, mulai dari yang paling sederhana.
super() pada Single Inheritance #
Pemakaian paling umum: anak memanggil __init__ induk agar bagian induk tetap terpasang, lalu menambahkan miliknya sendiri. Pola yang sama berlaku untuk method biasa — anak memanggil versi induk lalu membungkus hasilnya:
class Buku:
def __init__(self, judul, penulis):
self.judul = judul
self.penulis = penulis
def deskripsi(self):
return f"{self.judul} karya {self.penulis}"
class BukuDigital(Buku):
def __init__(self, judul, penulis, format_file):
super().__init__(judul, penulis)
self.format_file = format_file
def deskripsi(self):
return f"{super().deskripsi()} [format: {self.format_file}]"
buku = BukuDigital("Laskar Pelangi", "Andrea Hirata", "EPUB")
print(buku.deskripsi())Output yang Dihasilkan:
Laskar Pelangi karya Andrea Hirata [format: EPUB]Mari kita telaah baris-baris kuncinya:
- Baris 11 (
super().__init__(judul, penulis)): baris ini menjalankan__init__milikBuku, sehingga attributejuduldanpenulisterpasang oleh kode yang sama dengan objectBukubiasa — tidak ada duplikasi logika. - Baris 12 (
self.format_file = format_file): setelah bagian induk beres, anak menambahkan attribute miliknya. - Baris 15 (
super().deskripsi()): anak tidak menyalin format teks induk; ia memanggilnya lalu membungkus hasilnya dengan informasi baru.
Pola super().init dan Hukum Wajibnya #
Mengapa super().__init__() harus selalu dipanggil? Karena tanpa panggilan itu, __init__ anak sepenuhnya menggantikan versi induk — attribute milik induk tidak pernah terpasang. Berikut buktinya dari domain keuangan:
class Rekening:
def __init__(self, pemilik, saldo):
self.pemilik = pemilik
self.saldo = saldo
class RekeningTabungan(Rekening):
def __init__(self, pemilik, saldo, bunga_tahunan):
super().__init__(pemilik, saldo)
self.bunga_tahunan = bunga_tahunan
def hitung_bunga(self):
return int(self.saldo * self.bunga_tahunan / 100)
tabungan = RekeningTabungan("Siti", 2000000, 5)
print(tabungan.pemilik)
print(tabungan.saldo)
print(tabungan.bunga_tahunan)
print(tabungan.hitung_bunga())Output yang Dihasilkan:
Siti
2000000
5
100000Lalu versi yang lupa memanggil super().__init__():
class Rekening:
def __init__(self, pemilik, saldo):
self.pemilik = pemilik
self.saldo = saldo
class RekeningTabungan(Rekening):
def __init__(self, pemilik, saldo, bunga_tahunan):
self.bunga_tahunan = bunga_tahunan
tabungan = RekeningTabungan("Siti", 2000000, 5)
print(tabungan.pemilik)Output yang Dihasilkan:
Traceback (most recent call last):
File "13c-error-tanpa-super.py", line 12, in <module>
print(tabungan.pemilik)
^^^^^^^^^^^^^^^^
AttributeError: 'RekeningTabungan' object has no attribute 'pemilik'Object berhasil dibuat tanpa satu pun peringatan — kegagalan baru muncul jauh kemudian, saat attribute milik induk dibaca. Nama file pada baris File "..." bisa berbeda di komputer lain; bentuk pesannya tetap sama. Aturan praktisnya: begitu anak mendefinisikan __init__ sendiri, panggil super().__init__() di dalamnya.
Cooperative init #
Pada hierarki berlian dari Chapter Method Resolution Order, kita melihat super() berpindah ke class yang tak terduga. Kekuatan ini bisa diarahkan menjadi pola yang rapi: setiap class menjalankan bagiannya lalu memanggil super().__init__() — semua bekerja sama (cooperative) sehingga seluruh rantai MRO tuntas:
class Layanan:
def __init__(self, nama):
print(f"Layanan.__init__({nama})")
self.nama = nama
class LayananPinjam(Layanan):
def __init__(self, nama):
print("LayananPinjam.__init__ dijalankan")
super().__init__(nama)
class LayananNotifikasi(Layanan):
def __init__(self, nama):
print("LayananNotifikasi.__init__ dijalankan")
super().__init__(nama)
class Perpustakaan(LayananPinjam, LayananNotifikasi):
def __init__(self, nama):
print("Perpustakaan.__init__ dijalankan")
super().__init__(nama)
perpus = Perpustakaan("Perpus Kota")
print("Nama layanan:", perpus.nama)Output yang Dihasilkan:
Perpustakaan.__init__ dijalankan
LayananPinjam.__init__ dijalankan
LayananNotifikasi.__init__ dijalankan
Layanan.__init__(Perpus Kota)
Nama layanan: Perpus KotaMari kita telaah hasilnya:
- Baris
Perpustakaan("Perpus Kota")memicu__init__milikPerpustakaan— awal rantai MROPerpustakaan → LayananPinjam → LayananNotifikasi → Layanan. - Setiap class menjalankan cetakannya, lalu meneruskan
namalewatsuper().__init__(nama)ke class berikutnya — termasuk dariLayananPinjamyang melompat keLayananNotifikasi, bukan keLayanan. Layanan.__init__yang paling ujung memasang attributenamatepat satu kali; seluruh rantai tuntas danperpus.namaterbaca normal.
Kunci pola cooperative: signature setiap __init__ di sepanjang rantai harus saling cocok (di sini sama-sama menerima nama). Ketika tiap class di rantai butuh parameter berbeda-beda, parameter keyword dan **kwargs menjadi alat baku — bentuknya dibahas pada chapter Arbitrary Arguments di Section Fungsi dan muncul kembali di framework-framework dunia nyata.
Bentuk Tanpa Argumen dan Mekanismenya #
super() yang selama ini kita tulis tanpa argumen sebenarnya punya bentuk eksplisit dua argumen:
class Buku:
def __init__(self, judul):
self.judul = judul
class BukuDigital(Buku):
def __init__(self, judul, format_file):
super(BukuDigital, self).__init__(judul)
self.format_file = format_file
buku = BukuDigital("Laskar Pelangi", "EPUB")
print(buku.judul, "-", buku.format_file)Output yang Dihasilkan:
Laskar Pelangi - EPUBBentuk super(BukuDigital, self) membaca: “mulai pencarian dari class setelah BukuDigital dalam MRO object self” — hasilnya sama dengan super() polos di posisi itu. Versi pendek bisa bekerja karena compiler Python mengisi dua argumen itu secara otomatis berdasarkan class tempat kode ditulis. Sejarahnya pun ringkas: pada Python 2 bentuk eksplisit adalah satu-satunya cara, dan bentuk tanpa argumen hadir sebagai penyederhanaan resmi sejak Python 3.
Dengan super() dikuasai, kotak peralatan OOP inti kita sudah lengkap: class dan object, attribute, method, hingga hierarki pewarisan. Chapter penutup Section ini membahas keterampilan meta yang paling sering dilupakan: menilai kapan semuanya itu memang layak dipakai.