Lua Metatable
Dalam jadual Lua kita boleh mengakses kekunci yang sepadan untuk mendapatkan nilai, tetapi kita tidak boleh beroperasi pada dua jadual.
Oleh itu, Lua menyediakan metatable (Metatable), yang membolehkan kami mengubah tingkah laku jadual Setiap tingkah laku dikaitkan dengan metamethod yang sepadan.
Sebagai contoh, menggunakan metatable kita boleh mentakrifkan cara Lua mengira operasi tambah a+b dua jadual.
Apabila Lua cuba menambah dua jadual, ia mula-mula menyemak sama ada salah satu daripada dua jadual itu mempunyai jadual meta, dan kemudian menyemak sama ada terdapat medan yang dipanggil "__tambah jika ditemui, nilai yang sepadan dipanggil". Untuk medan masa nyata seperti "__add", nilai sepadannya (selalunya fungsi atau jadual) ialah "meta-method".
Terdapat dua fungsi yang sangat penting untuk mengendalikan metatable:
setmetatable(table, metatable): Set metatable untuk jadual yang ditentukan ( metatable) , jika nilai kunci __metatable wujud dalam metatable (metatable), setmetatable akan gagal.
getmetatable(table): Mengembalikan jadual meta objek.
Contoh berikut menunjukkan cara menetapkan metatable untuk jadual tertentu:
mytable = {} -- 普通表 mymetatable = {} -- 元表 setmetatable(mytable,mymetatable) -- 把 mymetatable 设为 mytable 的元表
Kod di atas juga boleh ditulis terus dalam satu baris:
rreeeYang berikut dikembalikan Metatable Objek:
mytable = setmetatable({},{})
__metamethod indeks
Ini ialah kunci metatable yang paling biasa digunakan.
Apabila anda mengakses jadual mengikut kunci, jika kunci itu tidak mempunyai nilai, Lua akan mencari kunci __index dalam jadual meta jadual (dengan andaian terdapat jadual meta). Jika __index mengandungi jadual, Lua mencari kunci yang sepadan dalam jadual.Kita boleh menggunakan arahan lua untuk memasuki mod interaktif untuk melihat:
getmetatable(mytable) -- 这回返回mymetatable
Jika __index mengandungi fungsi, Lua akan memanggil fungsi itu, dan jadual serta kunci akan menjadi sebagai Parameter dihantar ke fungsi.
Metamethod __index menyemak sama ada elemen itu wujud dalam jadual Jika ia tidak wujud, hasil pulangan adalah tiada, hasilnya dikembalikan oleh __index.
$ lua Lua 5.3.0 Copyright (C) 1994-2015 Lua.org, PUC-Rio > other = { foo = 3 } > t = setmetatable({}, { __index = other }) > t.foo 3 > t.bar nil
Hasil keluaran contoh ialah:
mytable = setmetatable({key1 = "value1"}, { __index = function(mytable, key) if key == "key2" then return "metatablevalue" else return nil end end }) print(mytable.key1,mytable.key2)
Analisis contoh:
tugasan jadual mytable ialah{key1 = "value1"}.
mytable menetapkan metatable dan metamethodnya ialah __index.
Cari kunci1 dalam jadual mytable Jika ditemui, kembalikan elemen tersebut Jika tidak ditemui, teruskan.
Cari key2 dalam jadual mytable Jika dijumpai, kembalikan metatablevalue Jika tidak dijumpai, teruskan.
Tentukan sama ada metatable mempunyai kaedah __index Jika kaedah __index ialah fungsi, panggil fungsi tersebut.
Dalam kaedah meta, semak sama ada parameter kunci "key2" dihantar masuk (mytable.key2 telah ditetapkan Jika parameter "key2" dihantar, "metatablevalue"). dikembalikan, jika tidak, nilai mytable yang sepadan dikembalikan.
Kita hanya boleh menulis kod di atas sebagai:
value1 metatablevalue
Ringkasan
Apabila Lua mencari jadual elemen Peraturan sebenarnya ialah 3 langkah berikut:
1. Jika dijumpai, kembalikan elemen tersebut
2. Tentukan sama ada jadual mempunyai metatable.
3. Tentukan sama ada metatable mempunyai kaedah __index Jika kaedah __index adalah nil, kembalikan nil jika kaedah __index ialah jadual, ulangi 1, 2, dan 3; kaedah __index ialah fungsi, nilai pulangan fungsi dikembalikan.
__newindex meta-method
__newindex meta-method digunakan untuk mengemas kini jadual, dan __index digunakan untuk mengakses jadual.
Apabila anda menetapkan nilai kepada indeks jadual yang hilang, penterjemah mencari metamethod __newindex: jika wujud, ia memanggil fungsi ini tanpa melaksanakan tugasan.
Contoh berikut menunjukkan aplikasi __newindex meta-method:
mytable = setmetatable({key1 = "value1"}, { __index = { key2 = "metatablevalue" } }) print(mytable.key1,mytable.key2)
Output pelaksanaan contoh di atas ialah:
mymetatable = {} mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable }) print(mytable.key1) mytable.newkey = "新值2" print(mytable.newkey,mymetatable.newkey) mytable.key1 = "新值1" print(mytable.key1,mymetatable.key1)
Dalam contoh di atas, meta- kaedah __newindex ditetapkan dalam jadual Apabila menetapkan nilai kepada kunci indeks baharu (kekunci baru) (mytable.newkey = "nilai baharu 2"), metamethod akan dipanggil tanpa memberikan nilai. Jika kunci indeks sedia ada (key1) diberikan, nilai akan diberikan tanpa memanggil meta-method __newindex.
Contoh berikut menggunakan fungsi rawset untuk mengemas kini jadual:
value1 nil 新值2 新值1 nil
Output pelaksanaan contoh di atas ialah:
mytable = setmetatable({key1 = "value1"}, { __newindex = function(mytable, key, value) rawset(mytable, key, "\""..value.."\"") end }) mytable.key1 = "new value" mytable.key2 = 4 print(mytable.key1,mytable.key2)
Tambah operator pada jadual
Contoh berikut menunjukkan operasi penambahan dua jadual:
new value "4"
Hasil keluaran pelaksanaan contoh di atas ialah:
-- 计算表中最大值,table.maxn在Lua5.2以上版本中已无法使用 -- 自定义计算表中最大值函数 table_maxn function table_maxn(t) local mn = 0 for k, v in pairs(t) do if mn < k then mn = k end end return mn end -- 两表相加操作 mytable = setmetatable({ 1, 2, 3 }, { __add = function(mytable, newtable) for i = 1, table_maxn(newtable) do table.insert(mytable, table_maxn(mytable)+1,newtable[i]) end return mytable end }) secondtable = {4,5,6} mytable = mytable + secondtable for k,v in ipairs(mytable) do print(k,v) end
Kunci __add disertakan dalam metatable dan operasi tambah dilakukan. Senarai operasi yang sepadan dalam jadual adalah seperti berikut:
模式 | 描述 |
---|---|
__add | 对应的运算符 '+'. |
__sub | 对应的运算符 '-'. |
__mul | 对应的运算符 '*'. |
__div | 对应的运算符 '/'. |
__mod | 对应的运算符 '%'. |
__unm | 对应的运算符 '-'. |
__concat | 对应的运算符 '..'. |
__eq | 对应的运算符 '=='. |
__lt | 对应的运算符 '<'. |
__le | 对应的运算符 '<='. |
__metakaedah panggilan
__metakaedah panggilan dipanggil apabila Lua memanggil nilai. Contoh berikut menunjukkan pengiraan jumlah elemen dalam jadual:
1 1 2 2 3 3 4 4 5 5 6 6
Output pelaksanaan contoh di atas ialah:
-- 计算表中最大值,table.maxn在Lua5.2以上版本中已无法使用 -- 自定义计算表中最大值函数 table_maxn function table_maxn(t) local mn = 0 for k, v in pairs(t) do if mn < k then mn = k end end return mn end -- 定义元方法__call mytable = setmetatable({10}, { __call = function(mytable, newtable) sum = 0 for i = 1, table_maxn(mytable) do sum = sum + mytable[i] end for i = 1, table_maxn(newtable) do sum = sum + newtable[i] end return sum end }) newtable = {10,20,30} print(mytable(newtable))
__tostring metamethod
__tostring metamethod digunakan untuk mengubah suai tingkah laku output jadual. Dalam contoh berikut, kami telah menyesuaikan kandungan output jadual:
70
Hasil output pelaksanaan contoh di atas ialah:
mytable = setmetatable({ 10, 20, 30 }, { __tostring = function(mytable) sum = 0 for k, v in pairs(mytable) do sum = sum + v end return "表所有元素的和为 " .. sum end }) print(mytable)
Daripada artikel ini, kita boleh tahu bahawa metatable boleh memudahkan fungsi kod kami Oleh itu, memahami metatable Lua membolehkan kami menulis kod Lua yang lebih ringkas dan lebih baik.