26. Method dan self
Kamu sudah sering memanggil fungsi yang tersimpan di tabel —
string.format, table.insert,
math.floor. Bab ini menunjukkan cara mendefinisikan fungsi
milikmu sendiri yang melekat pada tabel tertentu, dan apa yang
sebenarnya dilakukan sintaks titik dua (obj:method()) di
balik layar. Titik dua ada di mana-mana di Roblox; memahaminya sekali
akan menjelaskan banyak kode Roblox.
Fungsi pada tabel, cara panjang
Fungsi pada tabel hanyalah sebuah nilai di kunci string:
local counter = { count = 0 }
function counter.step(c)
c.count = c.count + 1
end
counter.step(counter)
counter.step(counter)
counter.step(counter)
print(counter.count) -- 3Fungsi counter.step menerima tabel itu sendiri sebagai
argumen pertama, lalu menggunakannya untuk memperbarui counter. Setiap
pemanggilan harus mengoper counter secara eksplisit:
counter.step(counter). Ini berfungsi, tapi terasa tidak
praktis.
Pintasan titik dua
Titik dua di Lua melakukan dua hal sekaligus — semacam pemanis sintaks yang membuat gaya pemanggilan yang terikat pada tabel jadi lebih bersih.
Memanggil dengan : secara otomatis
mengoper tabel sebagai argumen pertama:
counter:step() -- exactly the same as counter.step(counter)Mendefinisikan dengan : secara otomatis
mendeklarasikan parameter bernama self yang menerima
tabel:
function counter:step()
self.count = self.count + 1
endDefinisi yang sama seperti sebelumnya, ditulis lebih ringkas. Gabungkan kedua pintasan:
local counter = { count = 0 }
function counter:step()
self.count = self.count + 1
end
counter:step()
counter:step()
counter:step()
print(counter.count) -- 3Di dalam tubuh fungsi, self hanyalah nama parameter
biasa. Tulis self.x untuk membaca sebuah field,
self.x = ... untuk mengubahnya. Nama self
adalah konvensi, bukan aturan — itu hanya parameter implisit yang dibuat
oleh definisi dengan titik dua.
Buka exercises/26/01-counter.lua. File itu sudah punya
counter:step. Tambahkan counter:reset yang
mengatur self.count kembali ke 0, lalu panggil
dari bagian bawah file.
Pemanggilan titik dua bawaan
Banyak fungsi bawaan menerima sintaks titik maupun titik dua. Kedua bentuk ini bisa dipertukarkan:
local name = "keiko"
print(string.upper(name)) -- KEIKO
print(name:upper()) -- KEIKO -- samename:upper() mengoper name sebagai argumen
pertama ke string.upper. Ini berfungsi karena string
membawa tautan implisit ke tabel string, sehingga method
string apa pun bisa dipanggil sebagai s:method(). Kamu akan
melihat ini di mana-mana dalam kode Lua sungguhan.
Objek game sederhana
Sintaks method sangat berguna ketika beberapa bagian state disatukan. Berikut seekor anjing dengan nama dan jumlah gonggongan yang tersisa:
local dog = {
name = "Rex",
barks_left = 3,
}
function dog:bark()
if self.barks_left <= 0 then
print(self.name .. " is hoarse.")
return
end
print(self.name .. ": Woof!")
self.barks_left = self.barks_left - 1
end
dog:bark() -- Rex: Woof!
dog:bark() -- Rex: Woof!
dog:bark() -- Rex: Woof!
dog:bark() -- Rex is hoarse.Tabel dog menyimpan state; method mengubahnya di setiap
pemanggilan. Ini adalah bagian dari pemrograman berorientasi objek yang
kamu butuhkan untuk bab berikutnya, dan pola yang sama yang kamu lihat
di Roblox: sebuah Instance (sebuah tabel) dengan method
seperti :Destroy(), :GetChildren(),
:Clone().
Kesalahan umum: mencampur dua bentuk
obj.method() dan obj:method()
bukan pemanggilan yang sama. Titik tidak
mengoper obj secara otomatis. Jika method didefinisikan
dengan :, memanggil dengan . dan lupa mengoper
obj membuat self menjadi nil:
dog.bark() -- error: attempt to index a nil value (local 'self')Solusinya cukup satu karakter: gunakan :.
Kesalahan sebaliknya — obj:method(obj) — mengoper
obj dua kali. Yang pertama masuk ke self, yang
kedua menjadi argumen tambahan. Biasanya diabaikan saja, tapi bisa
membingungkan saat debugging.
PR
Soal 1 — Objek counter
Buka exercises/26/homework/01-counter-object.lua. Buat
tabel counter dengan field dan method berikut:
counter.count— mulai dari0.counter:inc()— menambahkan1.counter:get()— mengembalikan nilai count saat ini.counter:reset()— mengaturcountkembali ke0.
Panggil secara berurutan dan cetak nilainya di setiap langkah.
Soal 2 — Anjing yang menggonggong
Buka exercises/26/homework/02-dog.lua. Buat tabel
dog dengan field name dan method
:bark() yang mencetak <name>: Woof!.
Buat anjing kedua dengan nama berbeda. Panggil keduanya
:bark() dan pastikan masing-masing mencetak namanya
sendiri.
Soal 3 — Objek kalkulator
Buka exercises/26/homework/03-calculator.lua. Buat tabel
calc dengan:
calc.value— mulai dari0.calc:add(n)— menambahkannkecalc.value.calc:sub(n)— mengurangi.calc:mul(n)— mengalikan.calc:show()— mencetak nilai saat ini dengan label.
Rangkaikan beberapa pemanggilan dan pastikan nilainya diperbarui sesuai harapan.
Tantangan — Stack
Buka exercises/26/homework/04-stack.lua. Buat tabel
stack yang berperilaku seperti stack:
stack.items— sebuah list.stack:push(v)— menambahkanvke atas.stack:pop()— menghapus dan mengembalikan item teratas.stack:peek()— mengembalikan item teratas tanpa menghapusnya (atauniljika kosong).stack:size()— mengembalikan jumlah item yang tersimpan.
Gunakan table.insert dan table.remove tanpa
argumen kedua — itu akan push dan pop di akhir list, perilaku stack yang
standar.
Bingung atau sudah selesai? Buka halaman solusi PR.