最近总是遇到如果通过脚本语言搭建一个OOP结构,于是针对Lua进行了解,发现需要用到其元表metatable来实现,则对Lua的metatable进行一个理解的整理
理解:
名称:元表,本身也是一个table
针对table进行一些定制设定,添加或改变table的一些行为
例如定义一些方法,例如定义一个table的相加行为
metatable设置方法:
setmetatable(table,metatable): 对指定 table 设置元表(metatable),如果元表(metatable)中存在 __metatable 键值,setmetatable 会失败。
getmetatable(table): 返回对象的元表(metatable)。
以下实例演示了如何对指定的表设置元表:
-- An highlighted block
mytable = {} -- 普通表
mymetatable = {} -- 元表
setmetatable(mytable,mymetatable) -- 把 mymetatable 设为 mytable 的元表
__index元方法
metabale最常用的键,访问table的时候,没有这个键值,如果这个键没有值,则查找该table中的metatable,若metatable存在的情况下,查找metatable中的__index键,如果__index包含表格,lua会在其中查找对应的键值,如果__index包含一个函数,则调用其函数,table和键作为参数。
__index元方法查看表中元素是否存在,如果不存在,返回结果为nil;如果存在则由__index返回结果。
总结
Lua查找一个表元素时的规则,其实就是如下3个步骤:
1.在表中查找,如果找到,返回该元素,找不到则继续
2.判断该表是否有元表,如果没有元表,返回nil,有元表则继续。
3.判断元表有没有__index方法,如果__index方法为nil,则返回nil;如果__index方法是一个表,则重复1、2、3;如果__index方法是一个函数,则返回该函数的返回值。
__newindex 元方法
__newindex 元方法用来对表更新,__index则用来对表访问 。
当你给表的一个缺少的索引赋值,解释器就会查找__newindex 元方法:如果存在则调用这个函数而不进行赋值操作。
以下实例演示了 __newindex 元方法的应用:
mytable = setmetatable({key1 = "value1"}, {
__newindex = function(mytable, key, value)
rawset(mytable, key, "\""..value.."\"")
end
})
mytable.key1 = "new value"
mytable.key2 = 4
print(mytable.key1,mytable.key2)
__call 元方法
__call 元方法在 Lua 调用一个值时调用
– 计算表中最大值,table.maxn在Lua5.2以上版本中已无法使用
– 自定义计算表中最大键值函数 table_maxn,即计算表的元素个数
function table_maxn(t)
local mn = 0
for k, v in pairs(t) do
if mn < k then
mn = k
end
end
return mn
end
定义元方法__call
mytable = setmetatable({10}, {
__call = function(mytable, newtable)
sum = 0
for i = 1, table_maxn(mytable) do
sum = sum + mytable[i]
end
for i = 1, table_maxn(newtable) do
sum = sum + newtable[i]
end
return sum
end
})
newtable = {10,20,30}
print(mytable(newtable))