30. Merancang sebuah class kecil — Solusi PR
File solusi .lua ada di
exercises/30/homework/solutions/.
Soal 1 — Class Counter
Solusi lengkap.
local Counter = {}
Counter.__index = Counter
function Counter.new()
return setmetatable({ count = 0 }, Counter)
end
function Counter:increment() self.count = self.count + 1 end
function Counter:get() return self.count end
function Counter:reset() self.count = 0 end
local c = Counter.new()
c:increment(); c:increment(); c:increment()
print(c:get()) -- 3
c:reset()
print(c:get()) -- 0Soal 2 — Health yang dibatasi
Cara berpikir tentangnya. Terapkan aturan "tetap di
antara 0 dan max" di dalam heal dan damage,
sehingga tidak ada pemanggil yang bisa mendorong health keluar dari
rentang tersebut.
Solusi lengkap.
local Health = {}
Health.__index = Health
function Health.new(max)
return setmetatable({ max = max, current = max }, Health)
end
function Health:heal(n)
self.current = self.current + n
if self.current > self.max then self.current = self.max end
end
function Health:damage(n)
self.current = self.current - n
if self.current < 0 then self.current = 0 end
end
function Health:get() return self.current end
local h = Health.new(100)
h:damage(30); print(h:get()) -- 70
h:heal(1000); print(h:get()) -- 100 (dibatasi di max)
h:damage(9999); print(h:get()) -- 0 (dibatasi di 0)Soal 3 — Sakelar lampu
Solusi lengkap.
local Switch = {}
Switch.__index = Switch
function Switch.new()
return setmetatable({ on = false }, Switch)
end
function Switch:toggle() self.on = not self.on end
function Switch:isOn() return self.on end
local s = Switch.new()
print(s:isOn()) -- false
s:toggle(); print(s:isOn()) -- true
s:toggle(); print(s:isOn()) -- falseself.on = not self.on membalik nilai boolean setiap kali
dipanggil — seluruh logika sakelar dalam satu baris.
Tantangan — Stack dengan pengaman
Masalah. :pop() pada stack kosong
mengembalikan nil alih-alih crash.
Solusi lengkap.
local Stack = {}
Stack.__index = Stack
function Stack.new()
return setmetatable({ items = {} }, Stack)
end
function Stack:push(v) table.insert(self.items, v) end
function Stack:pop() return table.remove(self.items) end
function Stack:size() return #self.items end
local s = Stack.new()
s:push("a"); s:push("b")
print(s:size()) -- 2
print(s:pop()) -- b
print(s:pop()) -- a
print(s:pop()) -- nil (kosong, tapi tidak crash)
print(s:size()) -- 0table.remove pada list kosong mengembalikan
nil alih-alih error, jadi pengamannya sudah ada di dalamnya
— tapi pahami kenapa ini aman.
Selesai?
Ini adalah akhir dari Bagian 6. Kamu sudah bisa membuat class, membuat banyak objek, melakukan pewarisan, meng-override method, dan merancang antarmuka publik yang bersih dan aman. Bagian 6 memiliki dua mini-proyek: Sistem Inventaris dan Pertarungan Monster, keduanya dibangun dari objek-objek yang bekerja sama.