lua __index __newindex 规则总结

Published 05-05-2017 17:32:23

__index 规则总结

lua 中元方法 __index 表示表中索引查找失败处理方法,lua 中基它 元方法

查找元表流程

  • 在表中查找,如果找到,返回该元素,找不到则继续
  • 判断该表是否有元表,如果没有元表,返回nil,有元表则继续
  • 判断元表中有没有__index方法,如果没有,则返回nil, 如果__index方法是一个表,则重复上面的步骤,如果__index方法是一个函数,则返回该函数的返回值

示例代码Gist

local a = {
  field1 = 1
}

local b = {
  field2 = 2
}

-- 声明表a  b 
-- 设置 a 的元表是 b
setmetatable(a, b)

print(a.field1) -- 1  
print(a.field2) -- nil, field2是 表b的,a现在并不会查找元表b,元表中未定义__index方法

b.__index = b -- 设置b的__index 为 b
print(a.field2) -- 2 打印2,因为设置__index为b,a中没有field2,从__index设置的表b查找

-- __index 也可以设置成函数,当被它调用时,会把被访问的表和索引作为参数传入
b.__index = function(t, key)
  print(key) -- 打印访问的key
  return t.field1 -- 写死返回field1
end

-- 结果
-- field2 
-- 1
-- __index 为函数,访问key是field2,访问的表是a,返回filed1,值为1
print(a.field2)

-- 结果
-- field3
-- 1
print(a.field3)

__newindex 规则总结

__newindex__index类似,__newindex用于对表中不存在的key赋值时(myTable[key] = value)处理

当对一个table中不存在的索引赋值时,在Lua中的执行流程:

  • 判断有没有元表
  • 元表中如果__newindex 是一个函数则调用,参数是table key value
  • 如果__newindex指向一个table,就在这个table中执行赋值

测试代码

local table_a = {}

local table_b = {}

--  设置table_b 的元表
setmetatable(table_b, { __newindex = table_a })

table_b.field1 = "field1"

--  table_b.field1 = "field1" 
-- 对table_b的操作 因为元表中__newindex 指向table_a,就在这个table_a中执行赋值
print(table_a.field1) -- 输出 field1
print(table_b.field1) -- 输出 nil


-- 如果是一个函数则调用,参数是table key value
setmetatable(table_b, { __newindex = function (t, key, value) 
  rawset(t, key, value .."_ext")
end })

table_b.field2 = "field2"
print(table_b.field2) -- 输出field2_ext