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:

python
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:

text
Laskar Pelangi karya Andrea Hirata [format: EPUB]

Mari kita telaah baris-baris kuncinya:

  1. Baris 11 (super().__init__(judul, penulis)): baris ini menjalankan __init__ milik Buku, sehingga attribute judul dan penulis terpasang oleh kode yang sama dengan object Buku biasa — tidak ada duplikasi logika.
  2. Baris 12 (self.format_file = format_file): setelah bagian induk beres, anak menambahkan attribute miliknya.
  3. 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:

python
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:

text
Siti
2000000
5
100000

Lalu versi yang lupa memanggil super().__init__():

python
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:

text
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:

python
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:

text
Perpustakaan.__init__ dijalankan
LayananPinjam.__init__ dijalankan
LayananNotifikasi.__init__ dijalankan
Layanan.__init__(Perpus Kota)
Nama layanan: Perpus Kota

Mari kita telaah hasilnya:

  1. Baris Perpustakaan("Perpus Kota") memicu __init__ milik Perpustakaan — awal rantai MRO Perpustakaan → LayananPinjam → LayananNotifikasi → Layanan.
  2. Setiap class menjalankan cetakannya, lalu meneruskan nama lewat super().__init__(nama) ke class berikutnya — termasuk dari LayananPinjam yang melompat ke LayananNotifikasi, bukan ke Layanan.
  3. Layanan.__init__ yang paling ujung memasang attribute nama tepat satu kali; seluruh rantai tuntas dan perpus.nama terbaca 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:

python
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:

text
Laskar Pelangi - EPUB

Bentuk 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.