Panduan ini untuk siapa
- Pembelajar yang sudah memahami fundamental Python dan function
- Developer yang ingin memodelkan entitas dunia nyata dengan struktur yang bersih
- Siapa pun yang bersiap membangun aplikasi lebih besar dengan komponen reusable
Apa yang akan Anda pelajari
- Cara kerja class dan object di Python
- Peran
__init__dan jenis method yang berbeda (instance, class, static) - Bagaimana inheritance, encapsulation, dan polymorphism meningkatkan desain
- Kapan dan mengapa memakai abstract base classes (
abc) - Kesalahan OOP umum dan cara menghindari overengineering
Mengapa topik ini penting
Saat project bertambah besar, script biasa menjadi sulit dirawat. OOP membantu Anda mengorganisasi data dan perilaku ke unit yang jelas (class) sehingga kode lebih mudah dibaca, diuji, dan dikembangkan.
Di Python, OOP bersifat praktis, bukan kaku. Anda bisa menggabungkan desain berorientasi objek dengan pola fungsional, lalu memilih struktur paling sederhana yang cocok dengan masalah Anda. Menguasai OOP memberi fondasi kuat untuk framework, API, dan codebase yang scalable.
Konsep inti
Classes, objects, dan constructor
Class adalah blueprint; object adalah instance dari blueprint tersebut.
class User:
def __init__(self, username, email):
self.username = username
self.email = email
def profile(self):
return f"{self.username} <{self.email}>"
user = User("katie", "[email protected]")
print(user.profile())
Expected output:
katie <[email protected]>
__init__ dijalankan ketika object baru dibuat. Method ini menginisialisasi state object.
Jenis method dan encapsulation
Class Python umumnya memakai tiga jenis method:
- Instance methods: beroperasi pada data object (
self) - Class methods: beroperasi pada konteks level class (
cls) - Static methods: logika utilitas terkait domain class tetapi tanpa state instance/class
class Temperature:
scale = "Celsius"
def __init__(self, celsius):
self._celsius = celsius
def to_fahrenheit(self):
return (self._celsius * 9 / 5) + 32
@classmethod
def from_fahrenheit(cls, fahrenheit):
celsius = (fahrenheit - 32) * 5 / 9
return cls(celsius)
@staticmethod
def is_valid(value):
return isinstance(value, (int, float))
Gaya penamaan _celsius menandakan atribut internal (encapsulation berbasis konvensi).
Konvensi visibilitas encapsulation di Python:
- Public attribute:
name(ditujukan untuk akses eksternal normal) - Protected-style attribute:
_balance(konvensi: penggunaan internal) - Private-style attribute:
__pin(name-mangled untuk mengurangi akses tidak sengaja)
class Wallet:
def __init__(self, owner, pin):
self.owner = owner # public
self._balance = 0 # protected-style
self.__pin = pin # private-style
def deposit(self, amount):
self._balance += amount
def check_pin(self, pin):
return self.__pin == pin
w = Wallet("Ava", "1234")
w.deposit(100)
print(w.owner) # public access
print(w._balance) # possible, but convention says internal
print(w.check_pin("1234"))
Inheritance, polymorphism, dan abstract base classes
Inheritance memungkinkan child class memakai ulang dan memperluas behavior parent. Polymorphism memungkinkan class berbeda berbagi interface yang sama.
Bentuk inheritance yang umum:
- Single inheritance: satu child mewarisi satu parent
- Multiple inheritance: satu child mewarisi banyak parent
- Multilevel inheritance: rantai class (Grandparent -> Parent -> Child)
Contoh tipe inheritance:
# Single inheritance
class Animal:
def speak(self):
return "..."
class Dog(Animal):
def speak(self):
return "Woof"
# Multiple inheritance
class FlyMixin:
def fly(self):
return "Flying"
class SwimMixin:
def swim(self):
return "Swimming"
class Duck(FlyMixin, SwimMixin):
pass
# Multilevel inheritance
class Vehicle:
def category(self):
return "Transport"
class Car(Vehicle):
def wheels(self):
return 4
class ElectricCar(Car):
def power_source(self):
return "Battery"
print(Dog().speak())
print(Duck().fly(), Duck().swim())
print(ElectricCar().category(), ElectricCar().wheels(), ElectricCar().power_source())
from abc import ABC, abstractmethod
class PaymentProcessor(ABC):
@abstractmethod
def pay(self, amount):
pass
class CardPayment(PaymentProcessor):
def pay(self, amount):
return f"Paid ${amount} by card"
class WalletPayment(PaymentProcessor):
def pay(self, amount):
return f"Paid ${amount} by wallet"
def checkout(processor, amount):
print(processor.pay(amount))
checkout(CardPayment(), 120)
checkout(WalletPayment(), 85)
Expected output:
Paid $120 by card
Paid $85 by wallet
Pola ini memudahkan extension sambil menjaga API tetap konsisten.
Sketsa UML sederhana (berbasis teks):
PaymentProcessor (abstract)
├── CardPayment
└── WalletPayment
Diagram class seperti ini membantu mendokumentasikan relasi untuk rekan tim sebelum implementasi.
Panduan langkah demi langkah
Langkah 1 — Buat model class sederhana
Mulai dengan satu class yang memiliki data dan behavior sekaligus.
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
if amount > self.balance:
raise ValueError("Insufficient balance")
self.balance -= amount
Ini memberi Anda unit yang bersih dengan tanggung jawab jelas.
Langkah 2 — Tambahkan inheritance untuk behavior khusus
Buat subclass untuk savings account dengan aturan tambahan.
class SavingsAccount(BankAccount):
def __init__(self, owner, balance=0, interest_rate=0.03):
super().__init__(owner, balance)
self.interest_rate = interest_rate
def apply_interest(self):
self.balance += self.balance * self.interest_rate
Gunakan super() untuk memakai ulang inisialisasi parent dengan bersih.
Langkah 3 — Perkenalkan interface polymorphic
Rancang kode yang bisa bekerja dengan class apa pun yang mengimplementasikan method yang sama.
class EmailNotifier:
def send(self, message):
print(f"Email: {message}")
class SMSNotifier:
def send(self, message):
print(f"SMS: {message}")
def notify_all(notifiers, message):
for notifier in notifiers:
notifier.send(message)
notify_all([EmailNotifier(), SMSNotifier()], "Payment received")
Ini menjaga business logic tetap fleksibel tanpa rantai if/elif untuk setiap tipe.
Contoh praktis
Contoh 1 — Model inventory product
Memodelkan product sebagai object membuat update state lebih jelas.
class Product:
def __init__(self, name, price, stock):
self.name = name
self.price = price
self.stock = stock
def sell(self, quantity):
if quantity > self.stock:
raise ValueError("Not enough stock")
self.stock -= quantity
def __str__(self):
return f"{self.name} | ${self.price} | stock={self.stock}"
laptop = Product("Laptop", 999, 5)
laptop.sell(2)
print(laptop)
Expected output:
Laptop | $999 | stock=3
Contoh 2 — Abstract report exporters
Gunakan abstract base classes untuk menegakkan method yang wajib.
from abc import ABC, abstractmethod
class ReportExporter(ABC):
@abstractmethod
def export(self, data):
pass
class CSVExporter(ReportExporter):
def export(self, data):
return f"CSV export: {data}"
class JSONExporter(ReportExporter):
def export(self, data):
return f"JSON export: {data}"
for exporter in [CSVExporter(), JSONExporter()]:
print(exporter.export({"users": 120}))
Expected output:
CSV export: {'users': 120}
JSON export: {'users': 120}
Pola ini berguna saat Anda mendukung banyak format output atau backend.
Kesalahan umum dan cara menghindarinya
- Mengubah semua script menjadi class terlalu cepat -> Mulai sederhana; perkenalkan class saat state + behavior memang cocok digabung.
- Mengekspos internal mutable secara sembarangan -> Gunakan method yang jelas (
deposit,withdraw) alih-alih perubahan langsung tanpa kontrol. - Rantai inheritance terlalu dalam -> Pilih composition saat inheritance mulai sulit dipahami.
- Mengabaikan konsistensi interface -> Jaga nama/parameter method tetap prediktif pada class yang saling terkait.
- Melupakan single responsibility -> Satu class sebaiknya mengerjakan satu tugas inti dengan baik.
Latihan cepat
- Bangun class
Studentdengan atribut (name,scores) dan method (add_score,average_score). - Buat parent class
Animaldengan subclassDogdanCat, masing-masing mengimplementasikan methodspeak(). - Definisikan abstract class
Storagelalu implementasikanLocalStorage+CloudStoragedengan interfacesave(data)yang sama.
Ringkasan utama
- OOP membantu menstrukturkan program Python yang lebih besar melalui komponen reusable dan testable.
__init__, jenis method, dan konvensi encapsulation adalah alat inti harian.- Inheritance dan polymorphism meningkatkan extensibility jika dipakai secara terukur.
- Abstract base classes membantu menegakkan kontrak pada desain multi-implementasi.
Langkah berikutnya
Lanjut ke [07. Dasar Struktur Data & Algoritma](./07-data-structures-and-algorithms-basics-ID.md). Di panduan berikutnya, Anda akan meninjau struktur inti, cara berpikir kompleksitas, dan pola sorting/searching penting yang dipakai di interview dan sistem nyata.
No Comments