lua元表
在 Lua table 中我们可以访问对应的key来得到value值,但是却无法对两个 table 进行操作。
因此 Lua 提供了元表(Metatable),允许我们改变table的行为,每个行为关联了对应的元方法。
例如,使用元表我们可以定义Lua如何计算两个table的相加操作a+b。
当Lua试图对两个表进行相加时,先检查两者之一是否有元表,之后检查是否有一个叫”add”的字段,若找到,则调用对应的值。”add”等即时字段,其对应的值(往往是一个函数或是table)就是”元方法”。
有两个很重要的函数来处理元表:
setmetatable(table,metatable):对指定table设置元表(metatable),如果元表(metatable)中存在__metatable键值,setmetatable会失败 。
getmetatable(table):返回对象的元表(metatable)。
__index 元方法
这是 metatable 最常用的键。
当你通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的index 键。如果index包含一个表格,Lua会在表格中查找相应的键。
Lua查找一个表元素时的规则,其实就是如下3个步骤:
1.在表中查找,如果找到,返回该元素,找不到则继续
2.判断该表是否有元表,如果没有元表,返回nil,有元表则继续。
3.判断元表有没有index方法,如果index方法为nil,则返回nil;如果index方法是一个表,则重复1、2、3;如果index方法是一个函数,则返回该函数的返回值。
__newindex 元方法
newindex 元方法用来对表更新,index则用来对表访问 。
当你给表的一个缺少的索引赋值,解释器就会查找__newindex 元方法:如果存在则调用这个函数而不进行赋值操作。
__call 元方法
__call 元方法在 Lua 调用一个值时调用。
__tostring 元方法
__tostring 元方法用于修改表的输出行为。
table存在两种行为:查询和修改(赋值),通过元方法index和newindex来改变table的这两种行为。
__index主要用于table的查询
table[key] 的访问过程,首先检查table表中是否存在key的字段,如果有则返回,否则检查是否有__index的元方法,没有返回nil,有则查找元方法。
__index元方法可以是一个函数,还可以是一个table。如果是一个函数,则以table和不存在的key作为参数方位该函数,
例如:__index = function(t,key)
如果是一个table时,就以相同的方式来访问这个table(即传入key访问元方法的table,如果存在则放回值,反之返回nil)
例如:__index = tab –此时会返回tab[key]的值
__index可以很好的实现具有默认值的table
function setDefaultValues(t,d)
local mt = {__index = function() return d end}
setmetatable(t, mt)
end
tab = {x=10,y=20}
print(tab.x ,tab.y,tab.z) --由于没有设置元方法则为nil
setDefaultValues(tab,100) --设置默认值(设置__index元方法)
print(tab.z) --检查到有__index的元方法则返回默认值
__newindex主要用于table的更新
当对table中不存在的索引赋值时,解释器就会查找__newindex元方法。如果有这个元方法,就调用这个元方法,而不是执行赋值。如果这个元方法是一个table,解释器就在table中进行赋值,而不是对原来的table。
local k = {}
local mt = {
__newindex = k
}
local t = {}
setmetatable(t, mt)
print("赋值前:")
for k,v in pairs(k) do
print(k ,v)
end
t[1] = 20
print("赋值后:t表中的值:")
for k,v in pairs(t) do
print(k ,v)
end
print("赋值后:k表中的值:")
for k,v in pairs(k) do
print(k ,v)
end