0Pricing
Lua Academy · Pelajaran

Pengantar Metatabel

Atur dan dapatkan metatabel dengan setmetatable/getmetatable.

Pengantar Metatabel adalah pelajaran Lua Academy gratis di CoddyKit. Ini adalah pelajaran 1 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.

Apa Itu Metatable?

metatable adalah tabel Lua biasa yang mengendalikan perilaku tabel lain. Saat Lua menemukan operasi yang tidak dapat dilakukannya pada sebuah tabel (seperti aritmetika atau pengindeksan kunci yang tidak ada), Lua mencari metamethod yang sesuai dalam metatable. Ini adalah mekanisme ekstensi Lua untuk pembebanan operator dan OOP.

local t = {}
local mt = {__index = function(_, k) return "default_" .. k end}

setmetatable(t, mt)

print(t.foo)    -- default_foo
print(t.bar)    -- default_bar
print(t[1])     -- default_1

setmetatable dan getmetatable

setmetatable(t, mt) menetapkan metatable t menjadi mt dan mengembalikan t. getmetatable(t) mengembalikan metatable, atau nil jika tidak ada. Anda dapat melindungi metatable agar tidak diubah dengan menetapkan mt.__metatable = "protected".

local t = {x = 10}
local mt = {}

setmetatable(t, mt)
print(getmetatable(t) == mt)   -- true

-- Protect metatable
mt.__metatable = "locked"
print(getmetatable(t))   -- locked
-- setmetatable(t, {})  -- ERROR: cannot change protected metatable

__index sebagai Tabel

Saat __index berupa tabel, Lua mencari kunci yang tidak ada dalam tabel tersebut. Inilah dasar pewarisan prototipe Lua. Jika kunci tersebut juga tidak ada dalam __index, Lua memeriksa metatable miliknya, dan seterusnya sepanjang rantai.

local Animal = {sound = "...", legs = 4}

local Dog = setmetatable({sound = "Woof"}, {__index = Animal})
local Cat = setmetatable({sound = "Meow"}, {__index = Animal})

print(Dog.sound)   -- Woof (own field)
print(Dog.legs)    -- 4 (from Animal)
print(Cat.sound)   -- Meow
print(Cat.legs)    -- 4

__index sebagai Fungsi

Saat __index berupa fungsi, Lua memanggilnya dengan tabel dan kunci yang tidak ada. Fungsi tersebut dapat menghitung atau mengambil nilai secara dinamis. Kembalikan nil dari __index untuk menunjukkan bahwa "kunci tidak ditemukan."

local dynamic = setmetatable({}, {
  __index = function(t, k)
    if k:sub(1,4) == "get_" then
      local field = k:sub(5)
      return function(self) return self[field] end
    end
    return nil
  end
})

dynamic.name = "Lua"
local getter = dynamic.get_name
print(getter(dynamic))   -- Lua

rawget dan rawset

rawget(t, k) membaca kunci tabel tanpa memicu __index. rawset(t, k, v) menetapkan kunci tanpa memicu __newindex. Gunakan keduanya untuk melewati metamethod saat Anda memerlukan akses tabel langsung di dalam metamethod agar rekursi tak berujung dapat dihindari.

local logged = setmetatable({}, {
  __newindex = function(t, k, v)
    print("Setting", k, "=", v)
    rawset(t, k, v)  -- bypass __newindex
  end
})

logged.x = 10   -- Setting x = 10
logged.x = 20   -- no log! key now exists in t
print(logged.x) -- 20

Beberapa Tabel Berbagi Metatabel

Satu metatabel dapat digunakan bersama oleh banyak tabel. Begitulah sistem kelas Lua bekerja: semua instans dari suatu kelas berbagi metatabel yang sama, yang menyimpan metode-metodenya. Perubahan pada metatabel akan memengaruhi semua instans.

local Mt = {
  __index = {
    greet = function(self)
      print("Hello from " .. (self.name or "?"))
    end
  }
}

local a = setmetatable({name="Alice"}, Mt)
local b = setmetatable({name="Bob"},   Mt)

a:greet()   -- Hello from Alice
b:greet()   -- Hello from Bob

Kolom __metatable

Menyetel mt.__metatable ke nilai apa pun menyebabkan getmetatable mengembalikan nilai tersebut, bukan metatabel yang sebenarnya. Ini mencegah pengguna memeriksa atau mengganti metatabel—berguna untuk enkapsulasi dan keamanan.

local secret = setmetatable({}, {
  __metatable = false,    -- hide metatable
  __index = {value = 42}
})

print(secret.value)        -- 42
print(getmetatable(secret)) -- false (not the real mt)
-- setmetatable(secret, {}) -- ERROR

Memeriksa Metatabel

Gunakan getmetatable(t) untuk memeriksa apakah suatu objek memiliki metatabel tertentu (untuk pemeriksaan tipe). Karena __metatable dapat menyamarkan metatabel yang sebenarnya, gunakan rawequal atau kolom penanda untuk pemeriksaan isinstance yang andal.

local MyClass = {}
MyClass.__index = MyClass
MyClass.__metatable = MyClass   -- use self as marker

function MyClass.new(x)
  return setmetatable({x=x}, MyClass)
end

local obj = MyClass.new(5)
print(getmetatable(obj) == MyClass)   -- true
print(obj.x)                           -- 5

Metatabel pada Non-Tabel

String dalam Lua sudah memiliki metatabel (modul string). Karena itu, Anda dapat memanggil s:upper() pada string apa pun. Anda tidak dapat menyetel metatabel pada string, angka, atau boolean dari Lua murni—hanya pada tabel dan userdata.

local s = "hello"
local mt = getmetatable(s)

-- String metatable has __index = string library
print(mt.__index == string)   -- true

-- So all string functions are methods:
print(s:upper())              -- HELLO
print(s:rep(3, "-"))          -- hello-hello-hello

Debugging dengan Metatabel

Anda dapat menambahkan metametode __tostring untuk mengatur cara tostring() dan print() menampilkan sebuah tabel. Ini sangat berguna untuk melakukan debugging pada objek yang kompleks.

local Point = {}
Point.__index = Point
Point.__tostring = function(p)
  return string.format("Point(%g, %g)", p.x, p.y)
end

function Point.new(x, y)
  return setmetatable({x=x,y=y}, Point)
end

local p = Point.new(3, 4)
print(tostring(p))   -- Point(3, 4)
print(p)             -- Point(3, 4)  (print calls tostring)

Pemeriksaan Singkat

Apa yang terjadi saat Anda mengakses kunci yang tidak ditemukan dalam tabel yang memiliki metatabel dengan __index yang disetel ke tabel lain?

Rangkuman: Metatabel

Ringkasan:

  • setmetatable(t, mt) / getmetatable(t)
  • __index: tabel → pencarian prototipe; fungsi → pengiriman dinamis
  • rawget/rawset melewati metametode
  • Metatabel bersama memungkinkan perilaku seperti kelas
  • __metatable melindungi metatabel dari pemeriksaan
  • __tostring mengatur keluaran pencetakan

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Pengantar Metatabel” gratis?

Ya — teks lengkap “Pengantar Metatabel” 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 “Pengantar Metatabel”?

Atur dan dapatkan metatabel dengan setmetatable/getmetatable. 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 1 dari 4.

Berapa lama pelajaran “Pengantar Metatabel” 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