Pendahuluan — mewarisi tanpa menyalin-tempel
Di Encapsulation & @property (#43) class Buku sudah punya state terlindungi. Hari ini kita buat variasi tanpa menduplikasi seluruh class: ebook, audiobook, atau edisi khusus yang “mirip buku” tapi punya data ekstra.
Inheritance (pewarisan) = class anak mewarisi attribute & method class induk, lalu boleh menambah atau meng-override yang perlu. Di Python: class Ebook(Buku):.
Catatan: di artikel ini Buku disederhanakan (attribute publik, tanpa @property) supaya pola super() dan override tidak tertutup detail validasi. Di proyek nyata, inheritance + encapsulation boleh digabung.
Prasyarat: Selesai Encapsulation (#43) (atau setidaknya nyaman dengan class,
__init__, method). Fondasi: Attribute &__init__(#42) · Class & Object (#41) · Mengenal OOP (#40).
Kenapa inheritance?
Tanpa pewarisan, kamu cenderung copy-paste Buku jadi Ebook, lalu bug perbaikan harus diubah di dua tempat. Dengan inheritance:
- Aturan bersama (mis.
pinjam()) tinggal di induk - Anak hanya menambah yang beda (format file, ukuran MB)
- Override method kalau perilaku perlu berbeda (mis. teks
info())
Jangan warisi hanya demi “hemat mengetik” — warisi karena memang adalah-sejenis (ebook adalah buku digital). Pola “punya” daftar object lain menunggu Composition (nanti di Seri 3).
Class induk Buku (titik berangkat)
Kita pakai versi ringkas yang fokus ke pewarisan. Validasi property tetap boleh seperti di Encapsulation (#43); di sini disederhanakan agar pola super() terlihat jelas:
class Buku:
def __init__(self, judul, penulis, tahun, stok=1):
self.judul = judul
self.penulis = penulis
self.tahun = tahun
self.stok = stok
def info(self):
return f"{self.judul} · {self.penulis} ({self.tahun}) · stok {self.stok}"
def pinjam(self):
if self.stok <= 0:
raise ValueError("stok habis")
self.stok -= 1
return self.stok
b = Buku("Belajar Python", "Sari", 2024, stok=2)
print(b.info())
class Ebook(Buku) — anak mewarisi induk
Sintaks: nama induk di dalam kurung. Instance Ebook bisa memakai method induk langsung:
class Buku:
def __init__(self, judul, penulis, tahun, stok=1):
self.judul = judul
self.penulis = penulis
self.tahun = tahun
self.stok = stok
def info(self):
return f"{self.judul} · {self.penulis} ({self.tahun}) · stok {self.stok}"
def pinjam(self):
if self.stok <= 0:
raise ValueError("stok habis")
self.stok -= 1
return self.stok
class Ebook(Buku):
"""Ebook adalah Buku + metadata file."""
pass
e = Ebook("Belajar Python", "Sari", 2024, stok=1)
print(e.info()) # diwarisi dari Buku
print(e.pinjam()) # juga diwarisi
print(isinstance(e, Ebook)) # True
print(isinstance(e, Buku)) # True — ebook juga "adalah" Buku
pass di tubuh class berarti “belum menambah apa-apa”. Berguna untuk memahami: anak kosong tetap bisa lahir lewat __init__ induk.
super().__init__ — menyiapkan state induk
Kalau anak punya __init__ sendiri, method itu menggantikan __init__ induk — Python tidak memanggil induk otomatis. Karena itu kamu hampir selalu perlu memanggil __init__ induk lewat super() agar attribute dasar ikut terisi:
class Buku:
def __init__(self, judul, penulis, tahun, stok=1):
self.judul = judul
self.penulis = penulis
self.tahun = tahun
self.stok = stok
def info(self):
return f"{self.judul} · {self.penulis} ({self.tahun}) · stok {self.stok}"
class Ebook(Buku):
def __init__(self, judul, penulis, tahun, stok=1, format_file="epub", ukuran_mb=1.0):
super().__init__(judul, penulis, tahun, stok)
self.format_file = format_file
self.ukuran_mb = ukuran_mb
e = Ebook("Belajar Python", "Sari", 2024, stok=1, format_file="pdf", ukuran_mb=4.5)
print(e.judul, e.format_file, e.ukuran_mb)
print(e.info()) # masih pakai info() milik Buku
Tanpa super().__init__(...), attribute seperti judul / stok sering belum ada — lalu muncul AttributeError saat method induk dijalankan. Bandingkan pola SALAH vs BENAR:
class Buku:
def __init__(self, judul, penulis, tahun, stok=1):
self.judul = judul
self.penulis = penulis
self.tahun = tahun
self.stok = stok
def info(self):
return f"{self.judul} · {self.penulis} ({self.tahun}) · stok {self.stok}"
# SALAH — anak punya __init__ tapi lupa super()
class EbookSalah(Buku):
def __init__(self, judul, penulis, tahun, stok=1, format_file="epub"):
# lupa: super().__init__(judul, penulis, tahun, stok)
self.format_file = format_file
# e = EbookSalah("Belajar Python", "Sari", 2024) # object lahir
# print(e.info()) # AttributeError: 'EbookSalah' object has no attribute 'judul'
# BENAR
class EbookBenar(Buku):
def __init__(self, judul, penulis, tahun, stok=1, format_file="epub"):
super().__init__(judul, penulis, tahun, stok)
self.format_file = format_file
e = EbookBenar("Belajar Python", "Sari", 2024, format_file="pdf")
print(e.judul, e.format_file)
print(e.info())
Ingat:
super()mencari implementasi di rantai induk (MRO). Untuk kasus satu induk seperti ini, anggap saja “panggil versi Buku”.
Override method info()
Anak boleh menulis ulang method dengan nama sama. Versi anak yang dipanggil saat object-nya Ebook:
class Buku:
def __init__(self, judul, penulis, tahun, stok=1):
self.judul = judul
self.penulis = penulis
self.tahun = tahun
self.stok = stok
def info(self):
return f"{self.judul} · {self.penulis} ({self.tahun}) · stok {self.stok}"
class Ebook(Buku):
def __init__(self, judul, penulis, tahun, stok=1, format_file="epub", ukuran_mb=1.0):
super().__init__(judul, penulis, tahun, stok)
self.format_file = format_file
self.ukuran_mb = ukuran_mb
def info(self):
dasar = super().info() # manfaatkan teks induk
return f"{dasar} · {self.format_file.upper()} ({self.ukuran_mb} MB)"
b = Buku("ESP32 Praktis", "Budi", 2023)
e = Ebook("Belajar Python", "Sari", 2024, format_file="pdf", ukuran_mb=4.5)
print(b.info())
print(e.info())
Pola sehat: override untuk melengkapi, bukan menyalin ulang seluruh logika induk. super().info() menjaga satu sumber kebenaran untuk bagian yang sama. Object Buku tetap memakai versi induk; object Ebook memakai versi anak.
Di dalam method anak, self tetap object Ebook — itu kenapa self.format_file tersedia setelah super().info(). Kalau kamu menulis ulang info() dari nol tanpa super(), teks dasar induk ikut terduplikasi; perbaikan format di Buku.info() tidak otomatis ikut ke anak.
Ebook dibahas di artikel; Audiobook kamu kerjakan di latihan.Pola Dasar — merancang inheritance
-
1
Pastikan “adalah-sejenis” Ebook adalah Buku. Kalau hanya “punya” buku, jangan inheritance.
-
2
Tulis class Anak(Induk)
class Ebook(Buku):— nama induk di kurung. -
3
Panggil super().__init__ Isi state bersama dulu, baru attribute khusus anak.
-
4
Override secukupnya Ubah
info()/ perilaku yang benar-benar beda; sisanya warisi. -
5
Uji induk dan anak Pastikan
Bukulama tidak rusak;isinstance(e, Buku)masuk akal.
Kode lengkap — salin & jalankan
Simpan sebagai perpustakaan_ebook.py, lalu python perpustakaan_ebook.py:
class Buku:
def __init__(self, judul, penulis, tahun, stok=1):
self.judul = judul
self.penulis = penulis
self.tahun = tahun
self.stok = stok
def info(self):
return f"{self.judul} · {self.penulis} ({self.tahun}) · stok {self.stok}"
def pinjam(self):
if self.stok <= 0:
raise ValueError("stok habis")
self.stok -= 1
return self.stok
class Ebook(Buku):
def __init__(self, judul, penulis, tahun, stok=1, format_file="epub", ukuran_mb=1.0):
super().__init__(judul, penulis, tahun, stok)
self.format_file = format_file
self.ukuran_mb = ukuran_mb
def info(self):
return f"{super().info()} · {self.format_file.upper()} ({self.ukuran_mb} MB)"
b = Buku("ESP32 Praktis", "Budi", 2023, stok=2)
e = Ebook("Belajar Python", "Sari", 2024, stok=1, format_file="pdf", ukuran_mb=4.5)
print(b.info())
print(e.info())
print("pinjam ebook:", e.pinjam())
print("isinstance ebook→Buku:", isinstance(e, Buku))
print("type(e) is Buku:", type(e) is Buku) # False — tipe persis tetap Ebook
Output yang diharapkan (kurang lebih):
ESP32 Praktis · Budi (2023) · stok 2
Belajar Python · Sari (2024) · stok 1 · PDF (4.5 MB)
pinjam ebook: 0
isinstance ebook→Buku: True
type(e) is Buku: False
Kesalahan umum
| Gejala | Penyebab tipikal | Perbaikan |
|---|---|---|
AttributeError: 'Ebook' object has no attribute 'judul' |
Anak punya __init__ tapi lupa super().__init__(...) |
Panggil super().__init__(...) sebelum pakai attribute induk |
TypeError: Buku.__init__() missing ... dari anak |
Argumen ke super().__init__ kurang / tertukar |
Samakan urutan parameter dengan induk |
| Override menghilangkan perilaku induk | Menulis ulang info() tanpa super().info() |
Panggil super() lalu tambah detail anak |
| Warisan terasa dipaksakan | Anak tidak benar-benar “adalah” induk (hanya reuse field) | Pertimbangkan composition (nanti) atau class terpisah |
Bingung isinstance vs tipe persis |
Mengira hanya type(e) is Buku |
isinstance(e, Buku) True untuk anak; detail polimorfisme di artikel berikutnya |
Latihan singkat
- Buat
class Audiobook(Buku)dengan attributedurasi_menit. Overrideinfo()supaya menampilkan durasi. - Di
Ebook.__init__, sengaja hapussuper().__init__sebentar — amati error, lalu kembalikan. - Buat list
[b, e]dan cetakitem.info()untuk tiap item. (Ini cuplikan Polymorphism — dibahas penuh di artikel berikutnya.)
FAQ singkat
Apakah anak otomatis mewarisi semua method?
Ya, kecuali di-override. Attribute instance tetap lahir lewat __init__ (biasanya lewat super()).
Apakah pinjam() harus ditulis ulang di Ebook?
Tidak, kalau perilakunya sama. Warisi saja. Override hanya jika ebook butuh aturan berbeda (mis. stok digital tak terbatas — itu keputusan desain nanti).
Bolehkah banyak induk (multiple inheritance)?
Boleh di Python, tapi untuk pemula: tahan dulu. Satu induk sudah cukup untuk fondasi.
Haruskah selalu override info()?
Tidak. Override hanya jika teks/perilaku induk kurang tepat untuk anak.
Kenapa di sini Buku tanpa @property?
Supaya fokus ke pewarisan. Setelah nyaman dengan super(), gabungkan lagi dengan pola Encapsulation (#43).
Apakah __nama (name-mangling) ikut “rusak” di anak?
Python mengubah __nama jadi _NamaClass__nama menurut class yang mendefinisikan-nya, jadi bentrok nama di subclass jarang terjadi. Untuk pemula: tetap utamakan _ seperti di #43; __ jarang diperlukan.
Kesimpulan & langkah berikutnya
Inheritance memakai hubungan “adalah-sejenis”: anak mewarisi induk, mengisi state lewat super().__init__, dan meng-override method bila perlu. Kamu menghindari copy-paste sekaligus menjaga satu tempat untuk aturan bersama.
Artikel ini adalah #44 (ini) — langkah kelima Seri 3 setelah Encapsulation (#43).
Lanjut ke artikel berikutnya — Polymorphism: daftar campuran Buku / Ebook diproses lewat interface yang sama, plus kapan isinstance boleh dipakai. (Belum di-hyperlink sampai artikel itu live.)
Seri 3 progress: 5/10 artikel live. Kamu di langkah #44 (ini). Prasyarat: Encapsulation (#43) · Attribute (#42) · Class & Object (#41) · Mengenal OOP (#40).