0Pricing
Lua Academy · Pelajaran

__tostring dan __len

Kendalikan representasi string dan operator # melalui metamethod.

__tostring dan __len adalah pelajaran Lua Academy gratis di CoddyKit. Ini adalah pelajaran 4 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.

Metametode __tostring

__tostring dipanggil saat tostring(obj) dipanggil, dan juga oleh print() (yang memanggil tostring pada setiap argumen). Definisikan metametode ini untuk menyediakan representasi objek kustom yang mudah dipahami manusia.

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

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

local p = Point.new(3.14, 2.72)
print(p)            -- Point(3.14, 2.72)
print(tostring(p))  -- Point(3.14, 2.72)

__len untuk Urutan

__len dipanggil saat operator # diterapkan pada tabel yang memiliki metametode ini. Dalam Lua 5.2+, __len selalu dipanggil untuk tabel; dalam 5.1, metametode ini hanya dipanggil untuk userdata. Gunakan untuk mendefinisikan "panjang" bagi wadah kustom.

local Queue = {}
Queue.__index = Queue
Queue.__len = function(q) return q._tail - q._head + 1 end

function Queue.new()
  return setmetatable({_data={},_head=1,_tail=0}, Queue)
end
function Queue:push(v)
  self._tail = self._tail + 1
  self._data[self._tail] = v
end
function Queue:pop()
  if self._head > self._tail then return nil end
  local v = self._data[self._head]
  self._head = self._head + 1
  return v
end

local q = Queue.new()
q:push("a"); q:push("b"); q:push("c")
print(#q)   -- 3

__tostring yang Informatif untuk Debugging

__tostring yang baik menyertakan nama tipe dan kolom-kolom penting. Untuk objek bertingkat, panggil tostring secara rekursif. Ini membuat debugging jauh lebih mudah daripada keluaran bawaan "table: 0x...".

local function tableToString(t, depth)
  depth = depth or 0
  if depth > 3 then return "{...}" end
  local parts = {}
  for k, v in pairs(t) do
    if type(v) == "table" then
      parts[#parts+1] = k.."="..tableToString(v, depth+1)
    else
      parts[#parts+1] = k.."="..tostring(v)
    end
  end
  return "{"..table.concat(parts,", ").."}"
end

local obj = {name="test", data={x=1,y=2}, active=true}
print(tableToString(obj))

__len vs Operator #

Untuk tabel tanpa metametode __len, #t mencari batas mana pun dari urutan (saat t[i] ~= nil dan t[i+1] == nil). Jika terdapat celah dalam tabel, hasilnya tidak dapat diprediksi. __len memungkinkan Anda mendefinisikan panjang yang pasti dan konsisten.

-- Table with hole: # is unpredictable
local t = {10, 20, nil, 40}
print(#t)  -- could be 2 or 4, undefined!

-- Custom container with authoritative length
local SafeList = {}
SafeList.__index = SafeList
SafeList.__len = function(s) return s._size end

function SafeList.new()
  return setmetatable({_data={}, _size=0}, SafeList)
end
function SafeList:add(v)
  self._size = self._size + 1
  self._data[self._size] = v
end
local s = SafeList.new()
s:add(1); s:add(nil); s:add(3)
print(#s)   -- 3 (always correct)

__tostring dalam Pesan Error

Saat Anda menggunakan objek error (tabel, bukan string), pendefinisian __tostring membuat pesan error mudah dibaca ketika error diteruskan dan diubah menjadi string.

local function makeError(code, msg)
  return setmetatable(
    {code=code, message=msg},
    {__tostring = function(e)
      return string.format("Error[%d]: %s", e.code, e.message)
    end}
  )
end

local ok, err = pcall(function()
  error(makeError(404, "resource not found"))
end)

if not ok then
  -- err is the error object (table)
  print(tostring(err))  -- may show table address...

__tostring dengan Pewarisan

Saat menggunakan OOP berbasis prototipe, definisikan __tostring pada metatabel kelas. Semua instans secara otomatis menggunakan __tostring milik kelas karena metatabel instans tersebut IS tabel kelas.

local Animal = {}
Animal.__index = Animal
Animal.__tostring = function(a)
  return string.format("%s(%s)", a._type or "Animal", a.name or "?")
end

function Animal.new(name, atype)
  return setmetatable({name=name, _type=atype}, Animal)
end

local cat = Animal.new("Whiskers", "Cat")
local dog = Animal.new("Rex", "Dog")
print(cat)  -- Cat(Whiskers)
print(dog)  -- Dog(Rex)

Menerapkan Set dengan __len dan __tostring

Gabungkan __len dan __tostring dalam satu tipe untuk menerapkan Set yang lengkap dan mudah digunakan.

local Set = {}
Set.__index = Set
Set.__len = function(s) return s._size end
Set.__tostring = function(s)
  local items = {}
  for k in pairs(s._data) do items[#items+1]=tostring(k) end
  table.sort(items)
  return "Set{" .. table.concat(items,", ") .. "}"
end

function Set.new(...)
  local obj = setmetatable({_data={},_size=0}, Set)
  for _, v in ipairs({...}) do
    if not obj._data[v] then obj._data[v]=true; obj._size=obj._size+1 end
  end
  return obj
end

local s = Set.new(3,1,4,1,5,9,2,6)
print(#s)         -- 7 (duplicates removed)
print(tostring(s)) -- Set{1, 2, 3, 4, 5, 6, 9}

Objek Numerik dengan Keduanya

Buat tipe pecahan dengan __tostring untuk tampilan dan __len sebagai jumlah digit (atau metrik khusus domain).

local Frac = {}
Frac.__index = Frac

local function gcd(a,b) return b==0 and a or gcd(b,a%b) end

function Frac.new(n,d)
  local g = gcd(math.abs(n), math.abs(d))
  return setmetatable({n=n//g, d=d//g}, Frac)
end

Frac.__tostring = function(f)
  if f.d==1 then return tostring(f.n) end
  return f.n .. "/" .. f.d
end

Frac.__add = function(a,b)
  return Frac.new(a.n*b.d + b.n*a.d, a.d*b.d)
end

local a = Frac.new(1,2)
local b = Frac.new(1,3)
print(a + b)   -- 5/6

Mengganti Perilaku Bawaan print

print Lua memanggil tostring pada setiap argumen yang dipisahkan oleh tab. Dengan __tostring yang telah didefinisikan, objek Anda akan ditampilkan secara bermakna dalam pernyataan print, pesan error, atau interpolasi string apa pun yang menggunakan tostring.

local Color = {}
Color.__index = Color
Color.__tostring = function(c)
  return string.format("#%02X%02X%02X", c.r, c.g, c.b)
end

function Color.new(r,g,b)
  return setmetatable({r=r,g=g,b=b}, Color)
end

local red   = Color.new(255,0,0)
local green = Color.new(0,255,0)
local blue  = Color.new(0,0,255)

print(red, green, blue)
-- #FF0000  #00FF00  #0000FF

__name dalam Lua 5.3+

Lua 5.3+ mendukung kolom __name dalam metatabel yang digunakan oleh pesan error bawaan untuk mengidentifikasi tipe. Meskipun tidak secara langsung memengaruhi tostring(), kolom ini muncul dalam pesan error saat runtime ketika Anda melakukan operasi yang tidak valid pada tipe tersebut.

local MyType = {}
MyType.__index = MyType
MyType.__name = "MyType"   -- used in error messages
MyType.__tostring = function(t)
  return "MyType(" .. tostring(t.value) .. ")"
end

local obj = setmetatable({value=42}, MyType)
print(obj)             -- MyType(42)

-- Error message will say "MyType" instead of "table"
-- pcall(function() local x = obj + 1 end)

Pemeriksaan Singkat

Kapan __tostring dipanggil?

Rangkuman: __tostring dan __len

Ringkasan:

  • __tostring: dipanggil oleh tostring() dan print()
  • __len: dipanggil oleh #obj; menyediakan panjang pasti untuk wadah kustom
  • Definisikan __tostring pada tabel kelas untuk semua instans
  • Gunakan __len saat struktur tabel mentah tidak memberikan nilai # yang benar
  • __name (5.3+) menamai tipe dalam pesan error

Pertanyaan yang Sering Diajukan

Apakah pelajaran “__tostring dan __len” gratis?

Ya — teks lengkap “__tostring dan __len” 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 “__tostring dan __len”?

Kendalikan representasi string dan operator # melalui 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 4 dari 4.

Berapa lama pelajaran “__tostring dan __len” 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