Pemrograman Python: Dari Nol sampai Proyek Mini

Belum masuk. Progresmu tidak tersimpan.

Masuk
  • Bab 9 dari 11
  • 30 menit
  • 1 latihan kode
  • 4 soal kuis

OOP: Class, Object, dan Empat Pilar

Di bab ini (6 bagian)
  1. Tujuan
  2. Kenapa perlu OOP?
  3. Class dan object
  4. Empat pilar OOP
  5. Kesalahan umum
  6. Rangkuman

Tujuan bab ini

  • Membedakan class dan object, lalu membuat class sendiri dengan __init__, self, atribut, dan method.
  • Memakai pewarisan dan override untuk membuat class anak yang perilakunya berbeda (polimorfisme).
  • Memahami enkapsulasi dengan konvensi _nama dan abstraksi lewat contoh rekening bank.

Kenapa perlu OOP?

Sampai bab sebelumnya, kamu menyimpan data di variabel, list, atau dictionary, lalu mengolahnya dengan fungsi. Cara itu sudah cukup untuk program kecil. Masalahnya muncul saat program membesar: data dan fungsi yang mengolahnya tersebar di mana-mana, dan kamu harus ingat fungsi mana yang cocok untuk data mana.

Pemrograman Berorientasi Objek (Object-Oriented Programming, OOP) mengumpulkan data dan perilaku yang saling berkaitan ke dalam satu wadah. Contohnya, sebuah rekening bank punya data (nama pemilik, saldo) dan perilaku (setor, tarik, cek saldo). Dengan OOP, semuanya dibungkus jadi satu.

Class dan object

Class adalah cetak biru. Object adalah wujud nyata yang dibuat dari cetak biru itu. Bayangkan class sebagai cetakan kue, dan object sebagai kue-kuenya. Satu cetakan bisa menghasilkan banyak kue, dan setiap kue boleh punya topping berbeda.

class Kucing:
    def __init__(self, nama, umur):
        self.nama = nama
        self.umur = umur

    def perkenalan(self):
        return f"Halo, aku {self.nama}, umurku {self.umur} tahun"

milo = Kucing("Milo", 2)
oyen = Kucing("Oyen", 4)

print(milo.perkenalan())
print(oyen.nama)

Output:

Halo, aku Milo, umurku 2 tahun
Oyen

Beberapa istilah penting dari contoh di atas:

IstilahArtiContoh
ClassCetak biru objekclass Kucing:
ObjectWujud dari classmilo = Kucing("Milo", 2)
__init__Konstruktor, jalan otomatis saat objek dibuatdef __init__(self, nama, umur):
selfMerujuk ke objek itu sendiriself.nama = nama
AtributData milik objekmilo.nama, milo.umur
MethodFungsi milik objekmilo.perkenalan()

Memahami self

Saat kamu menulis milo.perkenalan(), Python sebenarnya memanggil Kucing.perkenalan(milo). Objek milo otomatis dikirim sebagai parameter pertama, dan parameter itu kita beri nama self. Karena itu setiap method di dalam class menulis self sebagai parameter pertama, walaupun kamu tidak mengisinya saat memanggil.

Nama self sebenarnya hanya kesepakatan, tapi semua programmer Python memakainya. Jangan diganti supaya kodemu mudah dibaca orang lain.

Setiap object punya data sendiri

Atribut yang dibuat lewat self menempel di masing-masing objek. Mengubah data satu objek tidak memengaruhi objek lain dari class yang sama:

milo.umur = 3
print(milo.umur, oyen.umur)
print(isinstance(milo, Kucing))

Output:

3 4
True

Fungsi isinstance() mengecek apakah sebuah objek dibuat dari class tertentu. Ini berguna saat kamu ingin memastikan jenis data sebelum mengolahnya.

Empat pilar OOP

Contoh class Hewan dan Kucing beserta empat pilar OOP

PilarInti
EnkapsulasiMembungkus data dan method dalam satu class
PewarisanClass anak mewarisi atribut dan method induk
PolimorfismeMethod dengan nama sama, perilaku berbeda
AbstraksiMenyembunyikan detail rumit di balik method sederhana

Pewarisan dan polimorfisme

Dengan pewarisan, kamu tidak perlu menulis ulang kode yang sama. Class anak menulis nama induk di dalam kurung.

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

    def suara(self):
        return "..."

class Kucing(Hewan):      # pewarisan
    def suara(self):      # override
        return "Meong!"

class Anjing(Hewan):
    def suara(self):
        return "Guk!"

for h in [Kucing("Milo"), Anjing("Bruno"), Hewan("Misteri")]:
    print(h.nama, h.suara())

Output:

Milo Meong!
Bruno Guk!
Misteri ...

Kucing dan Anjing tidak menulis __init__ sendiri, tapi tetap punya atribut nama karena mewarisinya dari Hewan. Keduanya menulis ulang method suara(). Ini disebut override. Hasilnya, perulangan di atas cukup memanggil h.suara() tanpa peduli jenis hewannya, dan setiap objek menjawab dengan caranya sendiri. Itulah polimorfisme.

Kalau class anak butuh __init__ sendiri, panggil konstruktor induk dengan super():

class Burung(Hewan):
    def __init__(self, nama, bisa_terbang):
        super().__init__(nama)
        self.bisa_terbang = bisa_terbang

Enkapsulasi dan abstraksi: contoh rekening bank

Saldo rekening sebaiknya tidak diubah sembarangan dari luar. Python tidak punya kata kunci private seperti Java. Sebagai gantinya ada konvensi: nama atribut yang diawali satu garis bawah, misalnya _saldo, berarti "ini untuk urusan internal, jangan diakses langsung". Python tidak melarangnya, tapi programmer lain akan paham maksudnya.

class Rekening:
    def __init__(self, pemilik, saldo_awal=0):
        self.pemilik = pemilik
        self._saldo = saldo_awal

    def setor(self, jumlah):
        if jumlah > 0:
            self._saldo += jumlah
        return self._saldo

    def tarik(self, jumlah):
        if jumlah > self._saldo:
            print("Saldo tidak cukup")
            return False
        self._saldo -= jumlah
        return True

    def cek_saldo(self):
        return self._saldo

rek = Rekening("Ani", 100000)
rek.setor(50000)
rek.tarik(200000)
rek.tarik(30000)
print(rek.pemilik, rek.cek_saldo())

Output:

Saldo tidak cukup
Ani 120000

Di sini dua pilar bekerja sekaligus. Enkapsulasi: data _saldo dan aturan mengubahnya ada di satu tempat, jadi saldo tidak bisa negatif lewat tarik(). Abstraksi: pengguna class cukup memanggil setor() dan tarik() tanpa perlu tahu cara saldo dihitung di dalamnya. Kalau nanti aturannya berubah, misalnya ada biaya admin, kamu cukup mengubah isi method, dan kode yang memakai Rekening tidak perlu disentuh.

Kesalahan umum

  • Lupa menulis self sebagai parameter pertama method, sehingga muncul TypeError: ... takes 0 positional arguments but 1 was given.
  • Menulis nama = nama di __init__ alih-alih self.nama = nama. Nilainya hanya jadi variabel lokal dan hilang setelah konstruktor selesai.
  • Salah ketik __init__ menjadi _init_ atau __int__. Konstruktor tidak terpanggil dan objek tidak punya atribut yang diharapkan.
  • Memanggil method tanpa kurung, misalnya rek.cek_saldo. Yang didapat adalah objek method, bukan nilainya.
  • Mengubah _saldo langsung dari luar class. Python mengizinkannya, tapi aturan di setor() dan tarik() jadi terlewati.

Rangkuman

  • Class adalah cetak biru, object adalah wujudnya. Satu class bisa menghasilkan banyak object.
  • __init__ adalah konstruktor yang jalan saat objek dibuat, dan self merujuk ke objek itu sendiri.
  • Atribut menyimpan data objek, method adalah fungsi milik objek.
  • Pewarisan memakai class Anak(Induk):, override menulis ulang method induk, dan polimorfisme membuat method yang sama berperilaku beda di tiap class.
  • Enkapsulasi di Python memakai konvensi _nama, sedangkan abstraksi menyembunyikan detail di balik method sederhana seperti setor() dan tarik().

Selesaikan bab ini

  1. 1. Baca materi
  2. 2. Latihan kode (1)
  3. 3. Kuis (4 soal)

Latihan kode: Class Rekening bank

Lengkapi class Rekening.

  • __init__(self, pemilik, saldo_awal=0) menyimpan pemilik dan saldo di atribut _saldo.
  • setor(jumlah) menambah saldo jika jumlah lebih dari 0, lalu mengembalikan saldo terbaru.
  • tarik(jumlah) mengurangi saldo dan mengembalikan True. Jika saldo tidak cukup, saldo tidak berubah dan kembalikan False.
  • cek_saldo() mengembalikan saldo.

Cek pemahaman

  1. 1Apa peran `self` di dalam method sebuah class?

  2. 2Apa yang dicetak kode berikut?

    class Hewan:
        def suara(self):
            return "..."
    
    class Anjing(Hewan):
        def suara(self):
            return "Guk"
    
    class Ikan(Hewan):
        pass
    
    for h in [Anjing(), Ikan()]:
        print(h.suara(), end=" ")
  3. 3Atribut yang diawali satu garis bawah, seperti `_saldo`, sama sekali tidak bisa diakses dari luar class.

  4. 4Penulisan `class Kucing(Hewan):` adalah contoh pilar OOP yang mana?