对Lua中__index和__newindex的基础理解
table对于元素的操作有 查询 和 赋值 两种。
__index和__newindex都是元方法,存在于元表中
这两种方法都不一定是一个table,也有可能是一个函数
__index 主要用于对table的查询
__index 主要用于对table的查询:
如果子表中的元素不存在,lua就会调用元表中的__index,去元表中查找对应的元素。
这里的元素并不局限于字段,也包括方法和table。
__index 例子:
local tableChild = {
age = "25",
}
local tableParent = {
__index = {
name = "憨憨的小韩",
age = "20"
},
}
setmetatable(tableChild, tableParent)
--子表中没有name,就去它元表中的index里面找name这个字段
print("子表name:" .. tostring(tableChild.name))
--子表已经有了age,直接输入value
print("子表age:" .. tostring(tableChild.age))
输入结果:
子表name:憨憨的小韩
子表age: 25
__newindex 主要用于对table的赋值更新
__newindex主要用于对table的赋值更新
如果想对子表中不存在的索引赋值时,lua就会调用元表中的__newindex元方法,
如果该方法是一个函数,就会执行这个方法
举个例子:
local tableChild = {
age = "25"
}
local newIndexTable = {}
local tableParent = {
__newindex = function (table, key, value)
print("想要访问 " .. key .. " 但子表中没有")
end,
}
setmetatable(tableChild, tableParent)
print("子表name:" .. tostring(tableChild.name))
tableChild.name = "憨憨的小韩"
print("子表name:" .. tostring(tableChild.name))
输入结果:
子表name:nil
想要访问 name 但子表中没有
子表name:nil
可以看出,当有__newindex的时候,给子表中不存在的元素赋值时,会执行__newindex指向的function,并且该操作并不会给子表新添加一个元素。
如果__newindex是一个table,lua就在这个table中进行赋值,而不对子表进行中的元素进行操作
举个例子:
local tableChild = {
age = "25"
}
local newIndexTable = {}
local tableParent = {
__newindex = newIndexTable
}
setmetatable(tableChild, tableParent)
print("子表name:" .. tostring(tableChild.name))
print("newIndexTablename:" .. tostring(newIndexTable.name))
tableChild.name = "憨憨的小韩"
print("子表name:" .. tostring(tableChild.name))
print("newIndexTablename:" .. tostring(newIndexTable.name))
输出结果:
子表name:nil
newIndexTablename:nil
子表name:nil
newIndexTablename:憨憨的小韩
上面这个例子可以看出,我们把newIndexTable这个table当做元表中的__newindex时,给子表中的name赋值,这个name并没有赋到子表当中,而会赋到了newIndexTable这个表中。
rawset
如果我们想通过__newindex去更新子表中元素的值的时候,我们需要使用rawset这个方法。
该方法最最最重要的功能就是使元方法失效。
还是以__newindex为函数的那个例子基础
local tableChild = {
age = "25"
}
local tableParent = {
__newindex = function (table, key, value)
print("给子表中的 " .. key .. " 赋值 " .. value)
rawset(table,key,value)
end,
}
setmetatable(tableChild, tableParent)
print("子表name:" .. tostring(tableChild.name))
tableChild.name = "憨憨的小韩"
print("子表name:" .. tostring(tableChild.name))
输出结果:
子表name:nil
给子表中的 name 赋值 憨憨的小韩
子表name:憨憨的小韩
以上本文总结的__index和__newindex的基础用法。