27. OOP sederhana dengan class — Solusi pekerjaan rumah
File solusi .py ada di
exercises/27/homework/solutions/.
Soal 1 — Class Point dengan move
Soal. Class Point dengan
__init__, distance, dan move.
Cara berpikir. Mulai dari class Point
di bab ini. Tambahkan satu method, move(dx, dy), yang
mengubah self.x dan self.y.
Solusi.
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)
def move(self, dx, dy):
self.x = self.x + dx
self.y = self.y + dy
a = Point(0, 0)
b = Point(3, 4)
print(a.distance(b)) # 5.0
a.move(1, 1)
print(a.x, a.y) # 1 1
print(a.distance(b)) # sqrt(2^2 + 3^2) ~ 3.6055...Kesalahan umum.
- Lupa
selfpadamovedandistance. Python akan komplain bahwa method menerima terlalu banyak argumen. - Menulis
x = xalih-alihself.x = xdi__init__. Field tidak akan tersimpan di instance sama sekali.
Soal 2 — Class Character
Solusi.
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
def report(self):
print(f"{self.name}: {self.hp} / {self.max_hp} HP (alive: {self.is_alive()})")
c = Character("Keiko", 100)
c.report()
c.take_damage(30)
c.report()
c.take_damage(80)
c.report()
c.heal(20)
c.report()Contoh output:
Keiko: 100 / 100 HP (alive: True)
Keiko: 70 / 100 HP (alive: True)
Keiko: 0 / 100 HP (alive: False)
Keiko: 20 / 100 HP (alive: True)
report adalah tempat yang tepat untuk f-string — tiga
nilai dalam satu baris template tetap.
Kesalahan umum.
- Membiarkan
hpturun negatif atau naik di atasmax_hp. Dua pengecekanifditake_damagedanhealmembatasi nilainya.
Soal 3 — Class Rectangle
Solusi.
class Rectangle:
def __init__(self, w, h):
self.w = w
self.h = h
def area(self):
return self.w * self.h
def perimeter(self):
return 2 * (self.w + self.h)
r1 = Rectangle(3, 4)
r2 = Rectangle(10, 2)
print(r1.area()) # 12
print(r1.perimeter()) # 14
print(r2.area()) # 20
print(r2.perimeter()) # 24Kesalahan umum.
- Menyimpan
widthdanheightsebagai local variable di level method alih-alihself.wdanself.h. Object ada agar field-nya tersimpan bersama instance di antara pemanggilan method.
Tantangan — Animal, Dog, Cat
Solusi.
# Base class
class Animal:
def __init__(self, name):
self.name = name
def describe(self):
print(f"I am {self.name}.")
# Dog inherits Animal
class Dog(Animal):
def __init__(self, name):
super().__init__(name)
def bark(self):
print(f"{self.name}: Woof!")
# Cat inherits Animal
class Cat(Animal):
def __init__(self, name):
super().__init__(name)
def meow(self):
print(f"{self.name}: Meow.")
rex = Dog("Rex")
whiskers = Cat("Whiskers")
rex.describe() # I am Rex.
whiskers.describe() # I am Whiskers.
rex.bark() # Rex: Woof!
whiskers.meow() # Whiskers: Meow.Dog dan Cat keduanya memanggil
super().__init__(name) agar constructor Animal
berjalan dan mengatur self.name. Setiap anak hanya
menambahkan apa yang unik bagi dirinya.
Kesalahan umum.
- Menghilangkan
super().__init__(name)di__init__anak. Makaself.nametidak pernah diatur, dandescribe()memunculkanAttributeError. - Mendefinisikan
__init__di anak tapi lupa memanggilsuper(). Constructor anak berjalan, tapi pengaturan field milik parent tidak.
Selesai?
Object berbasis class (Point, Character,
Rectangle) dan rantai inheritance kecil
(Animal -> Dog/Cat) kini ada
di kotak peralatanmu. Tiga bab berikutnya membangun di atas ini:
Banyak object bersama mengelola koleksi instance,
Inheritance mendalam mengkhususkan satu class dari
class lain, dan Merancang class kecil membuat class
nyaman digunakan.