这种修改会覆盖原本该值可能存在的相应的预定义行为
lua中的每个值都可以有一个元表 只是table和userdata可以有各自独立的元表 而其他类型的值共享其类型所属的单一元表
lua代码只能设置table的元表 其他类型值的元表只能通过C代码设置
多个table可以共享一个通用的元表 并且每个table只能有一个元表
一、__index元方法(主要用于处理调用table中不存在的字段)
lua查找表中元素的规则
(1)先在表中查找 如果找到 返回该元素的值 找不到进行第(2)步
(2)判断该表是否具有元表 如果没有 返回nil 如果有 进行第(3)步
(3)判断元表中是否具有__index方法 如果__index为nil 则返回nil 如果__index方法是一个表 重复(1)(2)(3) 如果__index方法是一个函数 则返回该函数的返回值
function main()
local t = {name = "hello"}
local mt = {__index = { money = 300,}} --t中不存在money字段 但是其元表mt为其做了备胎处理
setmetatable(t, mt)
print("name = ".. t.name) --hello
print("money = "..t.money) --300
end
function main()
local t = {name = "hello"}
local mt = {__index = function()return 3000 end}
setmetatable(t, mt)
print("name = ".. t.name) --hello
print("money = "..t.money) --3000 __index是一个函数 返回其函数的返回值
end
father = {house = 1}
son = {car = 1}
setmetatable(son, father)
print(son.house) --首先 son中没有house字段 但是它有元表 查找其元表并没有__index方法 所以返回nil
上面刚提到的__index也可以是一个函数 当它是一个函数的时候 lua会调用此函数 table和键会作为参数传递给函数
__index元方法查看表中元素是否存在 如果不存在 返回结果为nil 如果存在 则由__index返回结果
二、__newindex 用来table的更新
t = {}
local mt = {__newindex = function(table,key,value)
print("key = "..key)
print("value = "..value)
key = value
end
}
function main()
local t = {a = "hello world"}
setmetatable(t, mt)
print("before xiugai")
print(t.a)
print("after xiugai")
t.a = "zhangyin"
print(t.a)
t.b = "say hello"
print(t.b) -- nil 进入了元表 但是并未赋值 因为给未定义的key赋值时会调用元方法不去赋值
end
main()
__newindex 用于table更新时 需要注意 假如我现在要修改的key并不存在于表中 但是此表有元表 继而调用元表里的__newindex方法 但是由于key不存在于表中 所以在调用元方法时 不会给其赋值 比如上述代码中的b 修改之前 元表中无__index方法 所以b的值返回nil 修改后 由于B未在表中有定义 所以并没有执行__newindex中的 key = value 是因为调用函数时要传入表table 要修改的key 以及对应的value 但是由于key不存在于表中 所以__newindex不进行赋值 所以使用__newindex的规则一 如果__newindex是一个函数 则在给table中不存在的字段赋值时 会调用这个函数 并且赋值不成功
function test()
local smartMan = {name = "none"}
local other = {name = "hello everyone i am so weiqu"}
local t1 = {}
local mt = {__index = smartMan,
__newindex = other
}
setmetatable(t1, mt)
print(" before other = " .. other.name); --hello everyone i am so weiqu
t1.name = "yyyyyyyyyy";
print(" after other = " .. other.name); ---yyyyyyyyyy
print(" t1 = " .. t1.name); ---none
end
test()
首先 给t1的name赋值时 name字段不存在 发现他有元表 只能通过元表里的__index找到了smartMan里的name字段 值为none
但是给表里不存在的字段赋值 此时_-newindex是一个表 所以修改了other表的值 所以使用__newindex规则二 如果__newindex是一个table,则在给table不存在的字段赋值时,会直接给__newindex的table赋值
以上两个例子总结一下:
如果__newindex是一个函数 则在给table中不存在的字段赋值时 会调用这个函数 并且赋值不成功
如果__newindex是一个table,则在给table不存在的字段赋值时,会直接给__newindex的table赋值