Metamethod Aritmetika
Beban lebih +, -, *, / dan operator lainnya dengan metamethod.
Metamethod Aritmetika adalah pelajaran Lua Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Lua Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Lua Academy mencakup 4 pelajaran total.
Nama-Nama Metametode
Lua mendefinisikan metametode untuk semua operator aritmetika. Saat Lua melihat operasi aritmetika pada tabel, Lua mencari metametode yang sesuai dalam metatabel tabel tersebut. Jika kedua operand berupa tabel, Lua memeriksa metatabel operand kiri terlebih dahulu.
-- Operator -> Metamethod
-- a + b -> __add
-- a - b -> __sub
-- a * b -> __mul
-- a / b -> __div
-- a % b -> __mod
-- a ^ b -> __pow
-- a // b -> __idiv
-- -a -> __unm (unary minus)
-- #a -> __len
print("Metamethods defined for all Lua operators")__add untuk Penjumlahan Vektor
Definisikan __add pada tabel vektor untuk mendukung +. Metametode menerima dua operand dan mengembalikan nilai baru. Kedua operand dapat berupa tabel atau salah satunya dapat berupa angka—metametode Anda harus menangani kedua kasus tersebut.
local Vec = {}
Vec.__index = Vec
Vec.__add = function(a, b)
return setmetatable({x=a.x+b.x, y=a.y+b.y}, Vec)
end
Vec.__tostring = function(v)
return string.format("Vec(%g,%g)", v.x, v.y)
end
function Vec.new(x,y) return setmetatable({x=x,y=y},Vec) end
local v1 = Vec.new(1,2)
local v2 = Vec.new(3,4)
print(tostring(v1 + v2)) -- Vec(4,6)__sub __mul __div
Definisikan __sub, __mul, dan __div dengan cara serupa. Untuk perkalian, tangani kasus table*table dan table*number dengan memeriksa tipe operand di dalam metametode.
local Vec = {}
Vec.__index = Vec
local function V(x,y) return setmetatable({x=x,y=y},Vec) end
Vec.__sub = function(a,b) return V(a.x-b.x, a.y-b.y) end
Vec.__mul = function(a,b)
if type(a)=="number" then return V(a*b.x, a*b.y)
elseif type(b)=="number" then return V(a.x*b, a.y*b)
else return a.x*b.x + a.y*b.y -- dot product
end
end
Vec.__tostring=function(v) return "("..v.x..","..v.y..")" end
local v = V(3,4)
print(tostring(v * 2)) -- (6,8)
print(tostring(V(1,0) - V(0,1))) -- (1,-1)__unm Negasi Unary
__unm adalah metametode untuk tanda minus unary, yang dipanggil saat Lua mengevaluasi -obj. Metametode ini menerima operand (nilai yang sama diteruskan dua kali demi konsistensi) dan mengembalikan nilai negasinya.
local Vec = {}
Vec.__index = Vec
local function V(x,y) return setmetatable({x=x,y=y},Vec) end
Vec.__unm = function(a) return V(-a.x, -a.y) end
Vec.__tostring = function(v)
return string.format("(%g,%g)", v.x, v.y)
end
local v = V(3, -4)
print(tostring(-v)) -- (-3,4)
print(tostring(-(-v))) -- (3,-4)__len untuk Panjang Kustom
__len dipanggil saat #obj dievaluasi pada tabel yang tidak memiliki urutan bilangan bulat mentah. Definisikan metametode ini untuk mengembalikan "panjang" yang bermakna bagi tipe kustom seperti himpunan, antrean, atau wadah berbobot.
local Bag = {}
Bag.__index = Bag
Bag.__len = function(b) return b._count end
function Bag.new()
return setmetatable({_count=0, _items={}}, Bag)
end
function Bag:add(item, qty)
self._items[item] = (self._items[item] or 0) + (qty or 1)
self._count = self._count + (qty or 1)
end
local bag = Bag.new()
bag:add("apple", 3)
bag:add("banana", 2)
print(#bag) -- 5__mod dan __pow
__mod menangani operator %; __pow menangani ^. Keduanya lebih jarang digunakan, tetapi berguna untuk tipe numerik kustom seperti bilangan bulat besar, pecahan, atau objek aritmetika modular.
local Modular = {}
Modular.__index = Modular
local M = 1000000007
local function mod(n)
return setmetatable({n = n % M}, Modular)
end
Modular.__add = function(a,b) return mod(a.n + b.n) end
Modular.__mul = function(a,b) return mod(a.n * b.n) end
Modular.__pow = function(a,b)
local r, base, exp = mod(1), a, b
while exp > 0 do
if exp%2==1 then r = r*base end
base = base*base; exp = math.floor(exp/2)
end
return r
end
print((mod(2) ^ 30).n) -- 73741817 (2^30 mod 1e9+7)__concat
__concat dipicu oleh operator .. saat setidaknya salah satu operand memiliki metametode ini. Dengan demikian, Anda dapat mendefinisikan penggabungan untuk tipe kustom atau membuat DSL yang dapat dirangkai.
local Builder = {}
Builder.__index = Builder
Builder.__concat = function(a, b)
local result = {}
for _, v in ipairs(a._parts) do result[#result+1] = v end
if type(b) == "string" then result[#result+1] = b
else for _, v in ipairs(b._parts) do result[#result+1] = v end end
return setmetatable({_parts=result}, Builder)
end
Builder.build = function(b) return table.concat(b._parts) end
local function S(s) return setmetatable({_parts={s}},Builder) end
print((S("Hello") .. ", " .. S("World") .. "!"):build())Metametode Perbandingan
__eq mendefinisikan == untuk tabel (hanya dipanggil saat kedua operand memiliki metatabel yang sama). __lt mendefinisikan <; __le mendefinisikan <=. Catatan: ~= menggunakan __eq; > menggunakan __lt dengan argumen dibalik; >= menggunakan __le.
local Vec = {}
Vec.__index = Vec
local function V(x,y) return setmetatable({x=x,y=y},Vec) end
Vec.__eq = function(a,b) return a.x==b.x and a.y==b.y end
Vec.__lt = function(a,b)
return (a.x^2+a.y^2) < (b.x^2+b.y^2) -- by magnitude
end
print(V(1,2) == V(1,2)) -- true
print(V(1,2) == V(1,3)) -- false
print(V(1,0) < V(2,0)) -- true (1 < 2)Merangkai Metametode
Karena metametode mengembalikan nilai (biasanya tabel baru), operasi dapat dirangkai secara alami. Setiap operator mengembalikan objek baru, dan operator berikutnya menggunakan hasil tersebut. Ini memungkinkan ekspresi aritmetika yang dapat dirangkai pada tipe kustom.
local Vec = {}
Vec.__index = Vec
local function V(x,y) return setmetatable({x=x,y=y},Vec) end
Vec.__add = function(a,b) return V(a.x+b.x,a.y+b.y) end
Vec.__mul = function(a,b)
if type(b)=="number" then return V(a.x*b,a.y*b) end
return V(a.x*b.x+a.y*b.y, 0) -- simplified
end
Vec.__tostring=function(v) return "("..v.x..","..v.y..")" end
local result = V(1,0) + V(0,1) * 3
print(tostring(result)) -- (1,3)Operasi Tipe Campuran
Saat Anda menulis vec * 2, operand kiri adalah tabel. Saat Anda menulis 2 * vec, operand kiri adalah angka (tidak memiliki metametode), sehingga Lua memeriksa metatabel operand kanan untuk mencari __mul. Tangani kedua urutan tersebut dalam metametode Anda.
local Vec = {}
Vec.__index = Vec
local function V(x,y) return setmetatable({x=x,y=y},Vec) end
Vec.__tostring = function(v) return "("..v.x..","..v.y..")" end
Vec.__mul = function(a, b)
if type(a) == "number" then
return V(a*b.x, a*b.y) -- scalar * vec
elseif type(b) == "number" then
return V(a.x*b, a.y*b) -- vec * scalar
end
return a.x*b.x + a.y*b.y -- dot product
end
print(tostring(V(1,2) * 3)) -- (3,6)
print(tostring(3 * V(1,2))) -- (3,6)Pemeriksaan Singkat
Metametode mana yang dipicu oleh -myTable?
Rangkuman: Metametode Aritmetika
Ringkasan:
__add __sub __mul __div __mod __pow __idiv— aritmetika biner__unm— tanda minus unary;__len— operator #__concat— operator..__eq __lt __le— operator perbandingan- Tangani tipe campuran (angka/tabel) di dalam metametode
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Metamethod Aritmetika” gratis?
Ya — teks lengkap “Metamethod Aritmetika” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Lua Academy, upgrade ke CoddyKit PRO. Kursus Lua Academy mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Metamethod Aritmetika”?
Beban lebih +, -, *, / dan operator lainnya dengan metamethod. Kamu berlatih Lua Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai Lua Academy?
Tidak diperlukan pengalaman sebelumnya. Lua Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.
Berapa lama pelajaran “Metamethod Aritmetika” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran Lua Academy ini?
Ya. Setiap pelajaran Lua Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Pengantar Metatabel
- __index dan __newindex
- Metamethod Aritmetika
- __tostring dan __len