lua __newindex 测试

前一篇有讲到:lua __index 测试

local mtbl = { pro2 = 1, name = "mtbl" }
local normal_tbl = { pro1 = 1, name = "normal_tbl" }
-- normal_tbl.pro2 = 2 -- normal_tbl 不存在 pro2 字段,lua 默认可以给 table 对象添加不存在的字段
-- print("nromal_tbl.pro2:" .. normal_tbl.pro2) -- 所以直接输出 nromal_tbl.pro2:2 是有值的
setmetatable(normal_tbl, mtbl)
mtbl.__index = mtbl

normal_tbl.pro2 = 2 -- 设置对 normal_tbl 不存在的 pro2 字段赋值
print("nromal_tbl.pro2:" .. normal_tbl.pro2) -- 通过输出了 2 的值
print("mtbl.pro2:" .. mtbl.pro2) -- 这里输出 mtbl.pro2 结果还是 1 的值

原因是因为 __index 是提供查找用的

如果要对一个 table 中不存在的 key 字段赋值,那么可以使用元表的 __newindex (相比:__index 多了个 new)

-- 如果我们设置了 元表的 __newindex 后
mtbl.__newindex = mtbl

-- 在给 normal_tbl 赋值不存在的 pro2 字段
normal_tbl.pro2 = 2
print("normal_tbl.pro2:" .. tostring(normal_tbl.pro2)) -- normal_tbl.pro2:2
print("mtbl.pro2:" .. tostring(mtbl.pro2)) -- mtbl.pro2:2

可以看到给 normal_tbl.pro2 赋值后 mtbl.pro2 的值也跟着变换了,这就是 __newindex 的作用

如果我们将 元表设置为 nil 后,再获取.pro2 字段,发现拿到的是 nil 值:

-- mtbl.__newindex = nil -- 设置 __newindex = nil normal_tbl.pro2 还是可以拿到值的
setmetatable(normal_tbl, nil) -- 将元表设置为 nil 后 normal_tbl.pro2 就拿不到值了
print("normal_tbl.pro2:" .. tostring(normal_tbl.pro2)) -- normal_tbl.pro2:2

上面测试的是 __newindex 为 table 时候的应用,同样我们也可以将 __newindex 设置为一个 function

可以参考官方提供的简述的文档:

__newindex: The indexing assignment table[key] = value. Like the index event, this event happens when table is not a table or when key is not present in table. The metavalue is looked up in the metatable of table.
Like with indexing, the metavalue for this event can be either a function, a table, or any value with an __newindex metavalue. If it is a function, it is called with table, key, and value as arguments. Otherwise, Lua repeats the indexing assignment over this metavalue with the same key and value. This assignment is regular, not raw, and therefore can trigger another __newindex metavalue.
Whenever a __newindex metavalue is invoked, Lua does not perform the primitive assignment. If needed, the metamethod itself can call rawset to do the assignment.

有一句:Like the index event, this event happens when table is not a table or when key is not present in table. The metavalue is looked up in the metatable of table.

意思是如果 原始 table 的字段 key 不存在的话,那么对 table.key = value 的话,就会对 table 查找 key 字段,如果找不到就会到 metatable 中的表来找(这个就是之前 __newindex = table 的方式)

一句:Like with indexing, the metavalue for this event can be either a function, a table, or any value with an __newindex metavalue.

意思是, __newindex 可以是一个函数,或是一个 table,或是其他的值

一句:If it is a function, it is called with table, key, and value as arguments.

意思是,如果 __newindex 是一个函数,那么将使用 table, key, value 三个参数

那么下面我们使用 function 的方式来设置 __newindex

function test_metatable_newidx_in_func()
	local mtbl = { pro2 = 1, name = "mtbl" }
	local normal_tbl = { pro1 = 1, name = "normal_tbl" }
	-- normal_tbl.pro2 = 2 -- normal_tbl 不存在 pro2 字段,lua 默认可以给 table 对象添加不存在的字段
	-- print("nromal_tbl.pro2:" .. tostring(normal_tbl.pro2)) -- 所以直接输出 nromal_tbl.pro2:2 是有值的
	setmetatable(normal_tbl, mtbl)
	mtbl.__index = mtbl

	-- normal_tbl.pro2 = 2 -- 设置对 normal_tbl 不存在的 pro2 字段赋值
	-- print("nromal_tbl.pro2:" .. tostring(normal_tbl.pro2)) -- 通过输出了 2 的值
	-- print("mtbl.pro2:" .. tostring(mtbl.pro2)) -- 这里输出 mtbl.pro2 结果还是 1 的值

	-- 这次我们使用的是 function 来设置 __newindex
	mtbl.__newindex = function(tbl, k, v)
		-- 在返回 __index 索引的 k 对应名字的字段值之前,我们输出一下打印内容
		print("tbl.name:" .. tbl.name .. " no found the key : '" .. k .. "', and set the value :" .. v)
		mtbl[k] = v
		-- 注意这里不要设置 tbl[k] = v,否则就出现无线递归
	end

	-- 在给 normal_tbl 赋值不存在的 pro2 字段
	normal_tbl.pro2 = 2
	print("normal_tbl.pro2:" .. tostring(normal_tbl.pro2)) -- normal_tbl.pro2:2
	print("mtbl.pro2:" .. tostring(mtbl.pro2)) -- mtbl.pro2:2

	-- mtbl.__newindex = nil -- 设置 __newindex = nil normal_tbl.pro2 还是可以拿到值的
	setmetatable(normal_tbl, nil) -- 将元表设置为 nil 后 normal_tbl.pro2 就拿不到值了
	print("normal_tbl.pro2:" .. tostring(normal_tbl.pro2)) -- normal_tbl.pro2:2

end

print("test_metatable_newidx_in_func()")
test_metatable_newidx_in_func()

--[=[
	输出:
	test_metatable_newidx_in_func()
	tbl.name:normal_tbl no found the key : 'pro2', and set the value :2
	normal_tbl.pro2:2
	mtbl.pro2:2
	normal_tbl.pro2:nil
]=]

References

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值