Lua 元表(Metatable) __index

Lua 元表(Metatable) __index

-- 表
animation = {
    
    }
animation.leg = 4

-- 表
bird = {
    
    }

-- 注意:__index 必须赋值,否则原表建立失败
animation.__index = animation

-- 将 表 bird 的元表设置为 表 animation
setmetatable(bird, animation)

local leg = bird.leg
print("leg:"..tostring(leg))
-- 输出: leg:4

-- bird 并没有定义 leg,为什么能访问到 bird.leg 值为 2

-- __index 元方法
-- 这是 metatable 最常用的键。
-- 当你通过键来访问 table 的时候,如果这个键没有值?
-- 那么Lua就会寻找该table的metatable 中的__index 键。
-- 如果__index包含一个表格,Lua会在表格中查找相应的键。

-- 所以当 bird 访问 leg 属性时,会首先在 bird 表内查找 leg
-- 如果 bird 表内没有 leg, 则会通过 __index 访问到 animation
-- 然后在表 animation 中获取 leg 的属性值,如果 表 animation
-- 没有字段 leg 则 返回 nil

bird.leg = 2

print("bird.leg:"..bird.leg)
-- 输出:bird.leg:2

print("animation.leg:"..animation.leg)
-- 输出 animation.leg:4

-- 当 bird.leg 被赋值后,下次再访问 bird.leg 将直接从 表 bird 中获取

当将 __index 赋值为 函数时

-- 表
animation = {
    
    }
animation.leg = 4

-- 表
bird = {
    
    }
bird.wing = 2

-- 当 __index 被赋值为一个函数时,__index 被访问时就会调用
-- 那个函数,table 和 建 会作为参数被传递给函数
-- __index 元方法查看表中元素是否存在,如果不存在,返回结果为nil
-- 如果存在则由 __index 返回结果

-- 下面匿名函数中 table 是 setmetatable(bird, animation) 中的 bird
animation.__index = function(table, key)
    print("key:"..key)

	for k, v in pairs(table) do
	    print(k.."  "..v)
	end

	if key == "leg" then
	    return 2
	end

    return "new:"..key
end

-- 将 表 bird 的元表设置为 表 animation
setmetatable(bird, animation)

local leg = bird.leg
print("leg:"..leg)

-- 输出
-- key:leg
-- wing  2
-- leg:2

-- 当 访问 bird.lge 时,从 __index 访问时调用了函数, 将 bird 和 leg 分别作为
-- 匿名函数的第一个 table:bird
-- 匿名函数的第二个 key:leg
-- 传递进函数
-- 经过逻辑判断返回结果

Lua 查找一个表元素时的规则,其实就是如下 3 个步骤:
1.在表中查找,如果找到,返回该元素,找不到则继续
2.判断该表是否有元表,如果没有元表,返回 nil,有元表则继续。
3.判断元表有没有 __index 方法,如果 __index 方法为 nil,
则返回 nil;如果 __index 方法是一个表,则重复 1、2、3;
如果 __index 方法是一个函数,则返回该函数的返回值

猜你喜欢

转载自blog.csdn.net/LIQIANGEASTSUN/article/details/127469584