Lua Academy · Pelajaran

__tostring dan __len

Kawal perwakilan rentetan dan operator # melalui kaedah meta.

Pelajaran 4 daripada 412 langkah

__tostring dan __len ialah pelajaran Lua Academy percuma di CoddyKit. Ini ialah pelajaran 4 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Lua Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Lua Academy merangkumi sejumlah 4 pelajaran.

Kaedah Metameta __tostring

__tostring dipanggil apabila tostring(obj) digunakan, dan juga oleh print() (yang memanggil tostring pada setiap argumen). Takrifkannya untuk menyediakan perwakilan objek tersuai anda yang boleh dibaca 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 Jujukan

__len dipanggil apabila operator # digunakan pada jadual yang mempunyai kaedah metameta ini. Dalam Lua 5.2+, __len sentiasa dipanggil untuk jadual; dalam 5.1, ia hanya dipanggil untuk data pengguna. Gunakannya untuk mentakrifkan "panjang" bagi bekas tersuai.

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 Terperinci untuk Penyahpepijatan

__tostring yang baik merangkumi nama jenis dan medan utama. Untuk objek bersarang, panggil tostring secara rekursif. Ini menjadikan penyahpepijatan jauh lebih mudah berbanding output lalai "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 berbanding Operator #

Bagi jadual tanpa kaedah metameta __len, #t mencari mana-mana sempadan jujukan (apabila t[i] ~= nil dan t[i+1] == nil). Jika terdapat lompang dalam jadual, hasilnya tidak dapat diramal. __len membolehkan anda mentakrifkan panjang yang muktamad 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 Mesej Ralat

Apabila anda menggunakan objek ralat (jadual dan bukannya rentetan), mentakrifkan __tostring menjadikan mesej ralat mudah dibaca apabila ralat itu merambat dan ditukar kepada rentetan.

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

Apabila menggunakan OOP berasaskan prototaip, takrifkan __tostring pada metajudual kelas. Semua tika akan menggunakan __tostring kelas secara automatik kerana metajudual tika IS jadual 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)

Melaksanakan Set dengan __len dan __tostring

Gabungkan __len dan __tostring dalam satu jenis untuk pelaksanaan Set yang lengkap dan mesra pengguna.

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 Berangka dengan Kedua-duanya

Cipta jenis pecahan dengan __tostring untuk paparan dan __len sebagai kiraan 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

Mengatasi Tingkah Laku print Lalai

print Lua memanggil tostring pada setiap argumen yang dipisahkan oleh tab. Dengan __tostring ditakrifkan, objek anda dipaparkan dengan bermakna dalam mana-mana pernyataan cetakan, mesej ralat atau interpolasi rentetan 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+ menyokong medan __name dalam metajudual, yang digunakan oleh mesej ralat lalai untuk mengenal pasti jenis. Walaupun ia tidak mempengaruhi tostring() secara langsung, medan ini muncul dalam mesej ralat masa jalan apabila anda melakukan operasi tidak sah pada jenis 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)

Semakan Pantas

Bilakah __tostring dipanggil?

Imbas Kembali: __tostring dan __len

Ringkasan:

  • __tostring: dipanggil oleh tostring() dan print()
  • __len: dipanggil oleh #obj; menyediakan panjang muktamad untuk bekas tersuai
  • Takrifkan __tostring pada jadual kelas untuk semua tika
  • Gunakan __len apabila struktur jadual mentah tidak memberikan # yang betul
  • __name (5.3+) menamakan jenis dalam mesej ralat
Percuma untuk bermula

Pelajari Lua dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
40
Pelajaran
159

Soalan Lazim

Adakah pelajaran “__tostring dan __len” percuma?

Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Lua Academy, termasuk “__tostring dan __len”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Lua Academy merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “__tostring dan __len”?

Kawal perwakilan rentetan dan operator # melalui kaedah meta. Anda berlatih Lua Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Lua Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Lua Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 4 daripada 4.

Berapa lamakah pelajaran “__tostring dan __len” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Lua Academy ini?

Ya. Setiap pelajaran Lua Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Pengenalan kepada Metajadual
  2. __index dan __newindex
  3. Kaedah Meta Aritmetik
  4. __tostring dan __len
← Kembali ke Lua Academy