2.4中"Lua does not perform the primitive assignment."的含义(关于__newindex)



from https://www.lua.org/manual/5.3/manual.html参见2.4节。关于元方法操作__newindex声明如下引用:

__newindex:索引分配表[key] = value。与索引事件类似,当table不是表或key不是表时,将发生此事件在表中。元方法在表中查找。

与索引一样,此事件的元方法可以是函数或表。如果它是一个函数,则调用table;键和值作为参数。如果它是一个表,Lua执行索引用相同的键和值赋值给该表。(这个任务是常规的,而不是原始的,因此可以触发另一个元方法。)

当存在__newindex元方法时,Lua不会执行__newindex元方法原始任务。(如有必要,元方法本身可以调用)

我问下面的人具体想说什么

"Lua不执行原始任务。(如有必要,元方法本身可以调用)">

这是否意味着,如果值是一个数字,这是一个原语,它不会通过元方法事件分配给提供的表,我们必须使用rawget或其他东西?这对我来说是非常困惑和矛盾的。

我想展示相同的示例来帮助您弄清楚这种混淆。基本赋值示例:

local test = {}
test['x'] = 1 -- equal to rawset(test, 'x', 1)
print(test['x']) -- 1
print(rawget(test,'x')) -- 1

当表test没有__newindex元方法时,原语赋值码test['x'] = 1等于rawset(test, 'x', 1)

然后是__newindex元方法示例:

local test = {}
setmetatable(test, {__newindex = function(t,key,value) end})
test['x'] = 1
print(test['x']) -- nil
print(rawget(test,'x')) -- nil

赋值test['x'] = 1将触发调用__newindex函数。如果__newindex不执行任何操作,则不执行任何操作,则test['x']将得到nil结果。

如果__newindex函数调用rawset:

local test = {}
setmetatable(test, {
__newindex = function(t,key,value) 
rawset(t,key,value) -- t:test key:'x' value:1
end})
test['x'] = 1
print(test['x']) -- 1
print(rawget(test,'x')) -- 1

代码具有与第一个示例相同的效果。所以手册说:

"Lua不执行基本赋值。(如有必要,元方法本身可以调用rawset来执行赋值。)">

那么问题是,我们如何使用__newindex?可用于分隔表中的新旧索引。

local test = {y = 1}
local newtest = {}
setmetatable(test, {
__newindex = 
function(t,key,value)
newtest[key] = value
end,
__index = newtest
})
test["x"] = 1
print(test['x']) -- 1
print(test['y']) -- 1
print(rawget(test, 'x')) -- nil
print(rawget(test, 'y')) -- 1

旧索引'x'和新索引'y'都可以被test[key]访问,并且可以被rawget(test, key)分开

最新更新