最近在项目中遇到框架上设计的lua只读表,在使用next对表判空时出现一直为nil的情况,后来研究了下只读表的生成,特此记录。
-- lua只读表的生成代码
XReadOnlyTable.Create = function(t)
for x, y in pairs(t) do
if type(x) == "table" then
if type(y) == "table" then
t[XReadOnlyTable.Create(x)] = XReadOnlyTable.Create(y)
else
t[XReadOnlyTable.Create(x)] = y
end
elseif type(y) == "table" then
t[x] = XReadOnlyTable.Create(y)
end
end
local mt = {
__metatable = "readonly table",
__index = t,
__newindex = function()
XLog.Error("attempt to update a readonly table")
end,
__len = function()
return #t
end,
__pairs = function()
local function stateless_iter(tbl, k)
local nk, nv = next(tbl, k)
if nk then return nk, nv end
end
return stateless_iter, t, nil
end
}
return setmetatable({}, mt) -- 返回一个空表
end
-- 测试代码
function Test()
local tableA = {1,2,3,4,5,6,7,8,9}
local tableB = XReadOnlyTable.Create(tableA)
XLog.Debug(next(tableB))
XLog.Debug(tableA[1])
end
-- 打印
nil
1
代码中可以看出,生成只读表的时候返回了一个空表,也就是说tableB是个带有自己设定好特殊原表的空表,在使用next调用tableB的时候,也是调用的这个空表,所以返回的是nil。
而按照索引对表进行访问的时候,由于访问空表找不到元素值,就去访问原表,找到了带有数据的tableA,返回指定索引数据。
在日后对表判空还是建议使用next,对于项目内自定义的只读表还要多加注意。