27. OOP sederhana dengan class

Bab 26 meletakkan beberapa method pada satu object yang dibuat secara manual. Itu berhasil untuk satu object, tapi membuang tenaga untuk banyak object dengan bentuk yang sama. Bayangkan 100 anjing — menyalin bark ke masing-masing secara terpisah tidak praktis. Bab ini menunjukkan class Python sebagai cetak biru: kamu mendefinisikannya sekali, lalu memanggilnya seperti function untuk membuat sebanyak mungkin instance yang kamu inginkan.

Class dengan __init__ dan method

Berikut adalah class Point. Baca dulu, lalu lihat penjelasannya:

import math

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

    def distance(self, other):
        dx = self.x - other.x
        dy = self.y - other.y
        return math.sqrt(dx * dx + dy * dy)

a = Point(0, 0)
b = Point(3, 4)
print(a.distance(b))   # 5.0

Apa yang terjadi:

  1. class Point: mendeklarasikan class — sebuah cetak biru. Semua method diindentasi di dalamnya.
  2. __init__(self, x, y) adalah constructor. Python memanggilnya secara otomatis ketika kamu menulis Point(0, 0). Ia mengatur field-field instance.
  3. self adalah instance yang sedang dibuat atau digunakan. Menulis self.x = x menyimpan x pada instance itu sendiri.
  4. Point(0, 0) membuat instance baru — object terpisah dengan x dan y-nya sendiri.
  5. def distance(self, other) adalah method biasa. self menerima instance tempat method dipanggil; other adalah argumen yang kamu teruskan.
  6. a.distance(b) memanggil method. Python mengisi self = a secara otomatis; kamu hanya meneruskan other = b.

Hasilnya: satu definisi class, banyak instance kecil, tanpa penyalinan.

Buka exercises/27/01-point.py. Tambahkan method move(self, dx, dy) yang menambah dx ke self.x dan dy ke self.y. Buat sebuah titik, gerakkan dua kali, lalu cetak posisinya.

Mengapa instance dan bukan sekadar dictionary?

Dictionary biasa bisa menyimpan data yang sama, tapi class mengelompokkan data dan perilaku di satu tempat. Class juga berperan sebagai factory: setiap pemanggilan Point(x, y) menghasilkan object baru yang independen. Dua instance tidak pernah berbagi field kecuali kamu membuatnya begitu secara eksplisit.

Class kedua: Character

Class karakter kecil yang bisa menerima kerusakan:

class Character:
    def __init__(self, name, hp):
        self.name = name
        self.hp = hp
        self.max_hp = hp

    def take_damage(self, amount):
        self.hp = self.hp - amount
        if self.hp < 0:
            self.hp = 0

    def heal(self, amount):
        self.hp = self.hp + amount
        if self.hp > self.max_hp:
            self.hp = self.max_hp

    def is_alive(self):
        return self.hp > 0

c = Character("Keiko", 100)
c.take_damage(30)
print(c.hp)            # 70
c.heal(50)
print(c.hp)            # 100  (capped at max_hp)
print(c.is_alive())    # True

Setiap pemanggilan Character(name, hp) menghasilkan instance baru dengan name, hp, dan max_hp-nya sendiri. Semua method ada di dalam class dan digunakan bersama oleh setiap instance.

Inheritance: satu class membangun dari class lain

Class anak mewarisi semua method dari parent dengan menyebutnya dalam tanda kurung:

class Animal:
    def __init__(self, name):
        self.name = name

    def describe(self):
        print(f"I am {self.name}.")

class Dog(Animal):
    def __init__(self, name):
        super().__init__(name)   # run Animal's __init__

    def bark(self):
        print(f"{self.name}: Woof!")

rex = Dog("Rex")
rex.describe()    # I am Rex.   (inherited from Animal)
rex.bark()        # Rex: Woof!  (defined on Dog)

class Dog(Animal): menyatakan bahwa Dog mewarisi dari Animal. super().__init__(name) memanggil constructor Animal agar field name diatur dengan benar.

rex.describe() berfungsi meskipun Dog tidak mendefinisikannya — Python menemukannya di Animal secara otomatis.

Itu sudah cukup untuk inheritance dalam kebanyakan kasus. Bab-bab berikutnya membahas lebih dalam tentang overriding dan merancang class dengan baik.

Pekerjaan Rumah

Soal 1 — Class Point dengan move

Buka exercises/27/homework/01-point.py. Buat class Point seperti di atas, ditambah method move(dx, dy) yang menambahkan delta ke posisi. Uji dengan membuat dua titik, memindahkan salah satu, lalu mencetak jarak antara keduanya.

Soal 2 — Class Character

Buka exercises/27/homework/02-character.py. Buat class Character dengan __init__(name, hp), take_damage(amount), heal(amount), dan is_alive(). Tambahkan method report() yang mencetak nama dan HP saat ini. Jalankan pertarungan kecil: rusak dua kali, sembuhkan sekali, dan cetak laporan setelah setiap aksi.

Soal 3 — Class Rectangle

Buka exercises/27/homework/03-rectangle.py. Buat class Rectangle dengan __init__(width, height), area(), dan perimeter(). Uji dengan dua persegi panjang berukuran berbeda.

Tantangan — Animal dan Dog

Buka exercises/27/homework/04-inheritance.py. Buat Animal dan Dog persis seperti contoh inheritance di bab ini. Kemudian tambahkan class anak kedua Cat yang juga mewarisi dari Animal dan memiliki method meow()-nya sendiri. Buat satu anjing dan satu kucing, panggil describe() pada keduanya, lalu bark() pada anjing dan meow() pada kucing.

Buntu atau sudah selesai? Buka halaman solusi pekerjaan rumah.