Langsung ke konten
KamusNgoding
Menengah Python 1 menit baca

OOP di Python: Class, Object, dan Inheritance

#python #oop #class #object #inheritance #encapsulation

Object-Oriented Programming (OOP) adalah paradigma pemrograman yang mengorganisasi kode ke dalam objek — entitas yang menggabungkan data (atribut) dan perilaku (metode).

Membuat Class dan Object

class Mahasiswa:
    # __init__ dipanggil saat objek dibuat
    def __init__(self, nama: str, nim: str, ipk: float):
        self.nama = nama    # atribut instance
        self.nim  = nim
        self.ipk  = ipk

    def perkenalan(self) -> str:
        return f"Halo, saya {self.nama} ({self.nim}), IPK: {self.ipk}"

    def lulus_cum_laude(self) -> bool:
        return self.ipk >= 3.75


# Membuat objek (instance)
mhs1 = Mahasiswa("Andi Pratama", "20210001", 3.82)
mhs2 = Mahasiswa("Budi Rahayu", "20210042", 3.45)

print(mhs1.perkenalan())
# Halo, saya Andi Pratama (20210001), IPK: 3.82

print(mhs1.lulus_cum_laude())   # True
print(mhs2.lulus_cum_laude())   # False

Atribut Class vs Atribut Instance

class Produk:
    pajak_persen = 11   # atribut class (dibagi semua instance)

    def __init__(self, nama: str, harga: float):
        self.nama  = nama    # atribut instance (unik per objek)
        self.harga = harga

    def harga_dengan_pajak(self) -> float:
        return self.harga * (1 + self.pajak_persen / 100)


p = Produk("Laptop", 10_000_000)
print(p.harga_dengan_pajak())    # 11100000.0

# Ubah pajak global
Produk.pajak_persen = 12
print(p.harga_dengan_pajak())    # 11200000.0

Enkapsulasi: _ dan __

class RekeningBank:
    def __init__(self, pemilik: str, saldo_awal: float):
        self.pemilik    = pemilik
        self.__saldo    = saldo_awal    # private (name mangling)
        self._riwayat   = []            # protected (konvensi)

    def setor(self, jumlah: float):
        if jumlah <= 0:
            raise ValueError("Jumlah setor harus positif")
        self.__saldo += jumlah
        self._riwayat.append(f"+{jumlah:,.0f}")

    def tarik(self, jumlah: float):
        if jumlah > self.__saldo:
            raise ValueError("Saldo tidak cukup")
        self.__saldo -= jumlah
        self._riwayat.append(f"-{jumlah:,.0f}")

    @property
    def saldo(self) -> float:
        return self.__saldo


rek = RekeningBank("Citra", 500_000)
rek.setor(200_000)
rek.tarik(100_000)
print(f"Saldo: Rp{rek.saldo:,.0f}")   # Saldo: Rp600,000
print(rek._riwayat)                    # ['+200,000', '-100,000']
# rek.__saldo  ← AttributeError (tidak bisa diakses langsung)

@property — Getter/Setter yang Elegan

class Lingkaran:
    def __init__(self, radius: float):
        self._radius = radius

    @property
    def radius(self) -> float:
        return self._radius

    @radius.setter
    def radius(self, nilai: float):
        if nilai < 0:
            raise ValueError("Radius tidak boleh negatif")
        self._radius = nilai

    @property
    def luas(self) -> float:
        import math
        return math.pi * self._radius ** 2


c = Lingkaran(5)
print(f"Luas: {c.luas:.2f}")   # Luas: 78.54

c.radius = 10
print(f"Luas: {c.luas:.2f}")   # Luas: 314.16

# c.radius = -1   ← ValueError

Inheritance (Pewarisan)

class Hewan:
    def __init__(self, nama: str, umur: int):
        self.nama = nama
        self.umur = umur

    def info(self) -> str:
        return f"{self.nama} ({self.umur} tahun)"

    def suara(self) -> str:
        return "..."


class Anjing(Hewan):
    def __init__(self, nama: str, umur: int, ras: str):
        super().__init__(nama, umur)   # panggil __init__ parent
        self.ras = ras

    def suara(self) -> str:
        return "Guk guk!"

    def info(self) -> str:
        return f"{super().info()} - Ras: {self.ras}"


class Kucing(Hewan):
    def suara(self) -> str:
        return "Meow!"


dog = Anjing("Rex", 3, "Husky")
cat = Kucing("Mimi", 2)

print(dog.info())    # Rex (3 tahun) - Ras: Husky
print(dog.suara())   # Guk guk!
print(cat.suara())   # Meow!

Polymorphism

Objek berbeda bisa diperlakukan seragam lewat antarmuka yang sama:

hewan_list = [
    Anjing("Buddy", 4, "Labrador"),
    Kucing("Kitty", 1),
    Anjing("Max", 2, "Poodle"),
]

for h in hewan_list:
    print(f"{h.nama}: {h.suara()}")

# Buddy: Guk guk!
# Kitty: Meow!
# Max: Guk guk!

__str__ dan __repr__

class Titik:
    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y

    def __str__(self) -> str:
        # Untuk print() — ramah pengguna
        return f"({self.x}, {self.y})"

    def __repr__(self) -> str:
        # Untuk debugging — representasi teknis
        return f"Titik(x={self.x}, y={self.y})"

    def __add__(self, other: "Titik") -> "Titik":
        # Overload operator +
        return Titik(self.x + other.x, self.y + other.y)


t1 = Titik(1, 2)
t2 = Titik(3, 4)
print(t1)           # (1, 2)
print(repr(t1))     # Titik(x=1, y=2)
print(t1 + t2)      # (4, 6)

Kesimpulan

KonsepDeskripsi
classCetak biru untuk membuat objek
__init__Konstruktor — dijalankan saat objek dibuat
Atribut instanceData unik per objek (self.nama)
Atribut classData dibagi semua instance
@propertyAkses atribut private dengan validasi
InheritanceAnak mewarisi atribut dan metode parent
PolymorphismObjek berbeda respons berbeda pada metode sama

Setelah menguasai OOP, coba terapkan pola desain profesional: Mengenal Design Patterns: Fondasi Arsitektur yang Scalable — belajar bagaimana class dan inheritance digunakan dalam pola desain Singleton dan Factory.

Artikel Terkait