leevis.com
leevis.com copied to clipboard
lua 表与元表总结
- lua中每个值都可以具有元表。元表中的方法称为元方法,定义原始值的一些行为。
- setmetatable(table,metatable): 对指定table设置元表(metatable)
- getmetatable(table): 返回对象的元表(metatable)。
元方法
-
__index
- 当访问一个table的字段时,如果table有这个字段,则直接返回对应的值;
- 找不到该字段,则判断该表是否有元表,没有元表返回nil,有元表则继续;
- 判断元表有没有__index方法,如果__index方法为nil,则返回nil;如果__index方法是一个表,则重复上述步骤;如果__index方法是一个函数,则返回该函数的返回值。
-
__newindex __newindex元方法与__index类似,__newindex用于更新table中的数据,而__index用于查询table中的数据
-
__tostring tostring会调用
-
__call table作为方法调用时会调用该元方法。
--[[lua表,
找函数是找的该表的元表的__function,
找变量是先找该表的变量,如果没有则再找该表的元表的__index,如果该index是table,则从该table里找对应的变量,如果该index是function,直接返回该function的值。
]]
local y = {}
function y.__tostring()
return "i am y"
end
y.a = "yy-a"
local x = {}
setmetatable(x, y)
---0----
print(x)
----1----
y.__index = y
print(x.a)
-----2---
y.__index = function() return 300 end
print(x.a)
-----3---
x.a = "xx-a"
print(x.a)
结果
i am y
yy-a
300
xx-a
- __mode 取值 'k v',表示表的key,val是弱引用。
local t1, t2 = {}, {}
local t3, t4 = {}, {}
local arr = setmetatable({}, {__mode = "v"}) --可以k或v或kv
arr[1] = t1
arr[2] = t2
arr[t3] = "t3"
arr[t4] = "t4"
t1 = nil
t3 = nil
collectgarbage()
for k, v in pairs(arr) do
print(k, v)
end
输出
#__mode = "k"
$ luajit ./t_test.lua
1 table: 0x0002d220
2 table: 0x0002d248
table: 0x000273a8 t4
#__mode = "v"
luajit ./t_test.lua
2 table: 0x00027438
table: 0x00027460 t3
table: 0x0002d220 t4
- __gc 垃圾回收时会调用该方法。lua5.1和luajit需要特殊支持。
function setmt__gc(t, mt)
local prox = newproxy(true)
getmetatable(prox).__gc = function() mt.__gc(t) end
t[prox] = true --关键,实际上是当t被回收时,prox也没有引用被回收。prox回收时会调用他元表的gc方法
return setmetatable(t, mt)
end
local iscollected = false
function gctest(self)
iscollected = true
print("cleaning up:", self)
end
local test = setmt__gc({}, {__gc = gctest})
collectgarbage()
assert(not iscollected)
test = nil
collectgarbage()
assert(iscollected)
- __gc 垃圾回收时调用。luajit和lua5.1需要特殊支持。
function setmt__gc(t, mt)
local prox = newproxy(true)
getmetatable(prox).__gc = function() mt.__gc(t) end
--让t的生命周期关联到prox。当t被回收时,prox也没有引用被回收。prox被回收时调用他元表的gc。
t[prox] = true
return setmetatable(t, mt)
end
local iscollected = false
function gctest(self)
iscollected = true
print("cleaning up:", self)
end
local test = setmt__gc({}, {__gc = gctest})
collectgarbage()
assert(not iscollected)
test = nil
collectgarbage()
assert(iscollected)