0Pricing
Lua Academy · Pelajaran

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

  1. Pengantar Metatabel
  2. __index dan __newindex
  3. Metamethod Aritmetika
  4. __tostring dan __len
← Kembali ke Lua Academy