原表解析
在 Lua table 中我们可以访问对应的 key 来得到 value 值,但是却无法对两个 table 进行操作(比如相加)。
因此 Lua 提供了元表(Metatable),允许我们改变 table 的行为,每个行为关联了对应的元方法。
- setmetatable(table,metatable): 对指定 table 设置元表(metatable),如果元表(metatable)中存在 __metatable 键值,setmetatable 会失败。
- getmetatable(table): 返回对象的元表(metatable)。
原表的定义
lua
mytable={} --普通表
mymetatable={} --元表
setmetatable(mytable,mymetatable) --将mymetatable设置为mytable的原表
--可简写如下:
mytable=setmetatable({},{})
getmetatable(mytable) --会返回mytable的元表
原表的应用
1. 变量赋值
解析如下:
lua
mymetatable={}
mytable=setmetatable({k1="v1"},{__newindex=mymetatable})
mytable.newkey="v2"
print(mytable.newkey,mymetatable.newkey)
--输出:nil v2 :普通表中不含"newkey",会调用元方法
mytable.k1="newV"
print(mytable.k1,mymetatable.k1)
--输出:newV nil :普通表中含有K1,会进行赋值,不再调用元方法
2.元方法调用函数
lua
mytable=setmetatable({k1="v1"},{
__newindex=function(mytable,k,v)--重写元方法
rawset(mytable,k,"\""..v.."\"")--rawset绕过原表机制,直接向原表中插入新键值对
end
})
mytable.k1="new v1";
mytable.k2=3;--由于初始表中不k2,则会向元表中查询元方法
print(mytable.k1,mytable.k2);
--输出:v1 "3"
3.合并元表
lua
function table_max(t)--获取原表最大键
--用"#"或者table.getn时,若键不连续,只会获取第一段的最大值
maxk=0;
for k,v in pairs(t) do
if type(k)=="number" and k>maxk then
maxk=k
end
end
return maxk
end
--实现两表合并
mytable=setmetatable({1,2,3},{__add=function(mytable,newtable)
local mytable_maxk=table_max(mytable)
for i=1,table_max(newtable) --遍历newtable
table.insert(mytable,mytable_maxk+i,newtable[i])
--将newtable中的数据插入到mytable中
end
return mytable
end
})
newtable={4,5,6}
mytable=mytable+newtable
for k,v in pairs(mytable) do
print(k.."--"..v)
end
元方法 | 运算操作 |
---|---|
__add | "+" |
__sub | "-" |
__mul | "*" |
__div | "/" |
__mod | "%" |
__unm | "-" |
__concat | "..." |
__eq | "==" |
__it | "<" |
__le | "<=" |
注:"__"两个下划线,__sub对应二元减(两个参数);__unm对应一元减(只有一个参数)。