OOP Ringkas¶
Object-Oriented Programming (OOP) adalah paradigma pemrograman yang menggunakan “objek” untuk memodelkan data dan perilaku. Bagian ini membahas konsep OOP dasar di Python.
Class dan Object¶
Class adalah blueprint untuk membuat object. Object adalah instance dari class.
# Mendefinisikan class
class Mahasiswa:
pass
# Membuat object (instance)
mhs1 = Mahasiswa()
mhs2 = Mahasiswa()
print(type(mhs1)) # <class '__main__.Mahasiswa'>
Atribut dan Method¶
Instance Attributes¶
class Mahasiswa:
def __init__(self, nama, nim):
self.nama = nama # instance attribute
self.nim = nim
# Membuat object dengan atribut
mhs = Mahasiswa("Ahmad", "12345")
print(mhs.nama) # Ahmad
print(mhs.nim) # 12345
Class Attributes¶
Atribut yang dibagi oleh semua instance:
class Mahasiswa:
universitas = "UDN" # class attribute
def __init__(self, nama, nim):
self.nama = nama
self.nim = nim
mhs1 = Mahasiswa("Ahmad", "12345")
mhs2 = Mahasiswa("Budi", "12346")
print(mhs1.universitas) # UDN
print(mhs2.universitas) # UDN
print(Mahasiswa.universitas) # UDN
Methods¶
Fungsi di dalam class:
class Mahasiswa:
def __init__(self, nama, nim):
self.nama = nama
self.nim = nim
self.nilai = []
def tambah_nilai(self, nilai):
self.nilai.append(nilai)
def rata_rata(self):
if not self.nilai:
return 0
return sum(self.nilai) / len(self.nilai)
def info(self):
return f"{self.nama} ({self.nim})"
mhs = Mahasiswa("Ahmad", "12345")
mhs.tambah_nilai(85)
mhs.tambah_nilai(90)
print(mhs.info()) # Ahmad (12345)
print(mhs.rata_rata()) # 87.5
Special Methods (Dunder Methods)¶
Method khusus dengan double underscore:
class Titik:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
"""Representasi string untuk print()"""
return f"Titik({self.x}, {self.y})"
def __repr__(self):
"""Representasi untuk debugging"""
return f"Titik(x={self.x}, y={self.y})"
def __eq__(self, other):
"""Perbandingan kesamaan (==)"""
return self.x == other.x and self.y == other.y
def __add__(self, other):
"""Operator penjumlahan (+)"""
return Titik(self.x + other.x, self.y + other.y)
p1 = Titik(1, 2)
p2 = Titik(3, 4)
print(p1) # Titik(1, 2)
print(p1 + p2) # Titik(4, 6)
print(p1 == p2) # False
Inheritance (Pewarisan)¶
Class dapat mewarisi atribut dan method dari class lain:
# Parent class (superclass)
class Orang:
def __init__(self, nama, umur):
self.nama = nama
self.umur = umur
def info(self):
return f"{self.nama}, {self.umur} tahun"
# Child class (subclass)
class Mahasiswa(Orang):
def __init__(self, nama, umur, nim):
super().__init__(nama, umur) # Panggil __init__ parent
self.nim = nim
def info(self):
return f"{super().info()}, NIM: {self.nim}"
class Dosen(Orang):
def __init__(self, nama, umur, nip):
super().__init__(nama, umur)
self.nip = nip
def info(self):
return f"{super().info()}, NIP: {self.nip}"
mhs = Mahasiswa("Ahmad", 20, "12345")
dosen = Dosen("Dr. Budi", 45, "98765")
print(mhs.info()) # Ahmad, 20 tahun, NIM: 12345
print(dosen.info()) # Dr. Budi, 45 tahun, NIP: 98765
Mengecek Inheritance¶
print(isinstance(mhs, Mahasiswa)) # True
print(isinstance(mhs, Orang)) # True
print(issubclass(Mahasiswa, Orang)) # True
Encapsulation¶
Menyembunyikan detail implementasi:
class BankAccount:
def __init__(self, saldo_awal):
self._saldo = saldo_awal # Protected (konvensi)
def deposit(self, jumlah):
if jumlah > 0:
self._saldo += jumlah
return True
return False
def withdraw(self, jumlah):
if 0 < jumlah <= self._saldo:
self._saldo -= jumlah
return True
return False
def get_saldo(self):
return self._saldo
akun = BankAccount(1000000)
akun.deposit(500000)
akun.withdraw(200000)
print(akun.get_saldo()) # 1300000
Private Attributes¶
class Rahasia:
def __init__(self):
self.__private = "Ini private" # Name mangling
def get_private(self):
return self.__private
obj = Rahasia()
# print(obj.__private) # Error: AttributeError
print(obj.get_private()) # Ini private
print(obj._Rahasia__private) # Bisa diakses tapi tidak disarankan
Property Decorator¶
Mengakses method seperti atribut:
class Lingkaran:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, value):
if value < 0:
raise ValueError("Radius tidak boleh negatif")
self._radius = value
@property
def luas(self):
return 3.14159 * self._radius ** 2
@property
def keliling(self):
return 2 * 3.14159 * self._radius
lingkaran = Lingkaran(5)
print(lingkaran.radius) # 5
print(lingkaran.luas) # 78.53975
lingkaran.radius = 10
print(lingkaran.luas) # 314.159
Polymorphism¶
Objek berbeda merespons method yang sama dengan cara berbeda:
class Hewan:
def suara(self):
pass
class Kucing(Hewan):
def suara(self):
return "Meow!"
class Anjing(Hewan):
def suara(self):
return "Woof!"
class Sapi(Hewan):
def suara(self):
return "Moo!"
def buat_suara(hewan):
print(hewan.suara())
hewan_list = [Kucing(), Anjing(), Sapi()]
for hewan in hewan_list:
buat_suara(hewan)
# Output:
# Meow!
# Woof!
# Moo!
Class Method dan Static Method¶
class Mahasiswa:
jumlah = 0
def __init__(self, nama):
self.nama = nama
Mahasiswa.jumlah += 1
@classmethod
def get_jumlah(cls):
"""Method yang bekerja dengan class, bukan instance"""
return cls.jumlah
@classmethod
def from_string(cls, data_string):
"""Factory method untuk membuat instance dari string"""
nama = data_string.split("-")[0]
return cls(nama)
@staticmethod
def validasi_nim(nim):
"""Method yang tidak memerlukan instance atau class"""
return len(nim) == 5 and nim.isdigit()
# Penggunaan
mhs1 = Mahasiswa("Ahmad")
mhs2 = Mahasiswa.from_string("Budi-12345")
print(Mahasiswa.get_jumlah()) # 2
print(Mahasiswa.validasi_nim("12345")) # True
print(Mahasiswa.validasi_nim("abc")) # False
Dataclass (Python 3.7+)¶
Cara ringkas membuat class untuk menyimpan data:
from dataclasses import dataclass, field
@dataclass
class Mahasiswa:
nama: str
nim: str
jurusan: str = "Informatika"
nilai: list = field(default_factory=list)
def rata_rata(self):
if not self.nilai:
return 0
return sum(self.nilai) / len(self.nilai)
mhs = Mahasiswa("Ahmad", "12345")
print(mhs) # Mahasiswa(nama='Ahmad', nim='12345', jurusan='Informatika', nilai=[])
mhs.nilai = [85, 90, 88]
print(mhs.rata_rata()) # 87.666...
# Otomatis mengimplementasikan __eq__
mhs2 = Mahasiswa("Ahmad", "12345")
print(mhs == mhs2) # True (jika nilai sama)
Abstract Base Class¶
Mendefinisikan interface yang harus diimplementasikan:
from abc import ABC, abstractmethod
class Bentuk(ABC):
@abstractmethod
def luas(self):
pass
@abstractmethod
def keliling(self):
pass
class Persegi(Bentuk):
def __init__(self, sisi):
self.sisi = sisi
def luas(self):
return self.sisi ** 2
def keliling(self):
return 4 * self.sisi
class Lingkaran(Bentuk):
def __init__(self, radius):
self.radius = radius
def luas(self):
return 3.14159 * self.radius ** 2
def keliling(self):
return 2 * 3.14159 * self.radius
# bentuk = Bentuk() # Error: tidak bisa instantiate ABC
persegi = Persegi(5)
print(persegi.luas()) # 25
Composition¶
Menggunakan objek lain sebagai komponen:
class Mesin:
def __init__(self, tenaga):
self.tenaga = tenaga
def nyalakan(self):
return f"Mesin {self.tenaga} HP menyala"
class Roda:
def __init__(self, ukuran):
self.ukuran = ukuran
class Mobil:
def __init__(self, merk, tenaga_mesin):
self.merk = merk
self.mesin = Mesin(tenaga_mesin) # Composition
self.roda = [Roda(17) for _ in range(4)]
def start(self):
return f"{self.merk}: {self.mesin.nyalakan()}"
mobil = Mobil("Toyota", 150)
print(mobil.start()) # Toyota: Mesin 150 HP menyala
Ringkasan Konsep OOP¶
Konsep |
Deskripsi |
|---|---|
Class |
Blueprint untuk membuat objek |
Object |
Instance dari class |
Attribute |
Data yang disimpan dalam objek |
Method |
Fungsi yang didefinisikan dalam class |
Inheritance |
Mewarisi atribut/method dari class lain |
Encapsulation |
Menyembunyikan detail implementasi |
Polymorphism |
Objek berbeda merespons method yang sama |
Abstraction |
Menyederhanakan kompleksitas |
Latihan¶
Buat class
Bukudengan atribut judul, penulis, tahun, dan method untuk menampilkan infoBuat class
Perpustakaanyang menyimpan koleksi buku dengan method pinjam dan kembalikanBuat hierarki class untuk bangun datar (Persegi, Persegi Panjang, Segitiga, Lingkaran)
Implementasikan class
Playlistyang menyimpan lagu dengan operasi add, remove, shuffle