metatable
类似封装了lua类型的操作符;
作用
lua的类型定义的一组操作符, 即当要对对象进行操作的时候,则查看元表里有没有对应的操作符; 如table的+对应__add, 该字段就是所谓在元方法(函数);lua 中每个值都有一个元表, 而只有table, userdata 有自己独立在元表,其它的类型都是共享一个元表;
table默认创建时元表为nil;
getmetatable(table)
与setmetatable(table, meta)
为元表操作函数;
lua中只能设置table的元表, 其它类型的值的元表只能通过C代码来设置;
元表示例
如下面的例子就是给table设置了一个+的算法来求集合:
local mt = {} Set = {} function Set.new(list) local re = {} setmetatable(re,mt) for _,v in ipairs(list) do re[v] = true end return re end function Set.Union(a,b) local re = {} for k in pairs(a) do re[k] = true end for k in pairs(b) do re[k] = true end return re end function Set.Print(lst) local l = {} for e in pairs(lst) do l[#l+1] = e end return "{"..table.concat(l,",").."}" end local lh = Set.new{"hbb",5,3,8} local lb = Set.new{"nm",2,6} mt.__add = Set.Union local l = lh + lb print(Set.Print(l))
metatable元表的禁止
想要用户即看不到元表又不能修改元表, 则可以将元表的__metatable属性赋值, 如上面的例子,如果
mt.__metatable = "hehe"
则getmetable会返回这个值, 而setmetatable则直接报错;
元方法
就是当table查询或修改的字段不存在时, 会访问元方法;
当对table进行字段查找和修改的时候,如果当前table里面没有对应的字段, 则会想metatable中的metamethod:__index, __newindex进行查找;
注: 这里是metatable的 而不是table自己的__index和__newindex字段
local mt = {} T = {} T.__index = function (t,k) print("this is the meta index") end T.__newindex = function (t,k,v) print("this is the meta newidex") end setmetatable(T,mt) T.Id = 4 --会打印thsi is the meta newindex, 但这里没有创建字段, -- 所以后面查询为空 print(T.Id) -- this is the meta index, nil'
rawget(t,k), rawset(t,k,v)
rawget(t,k) 就是访问table t的k字段时, 不会访问到__index元方法;
同理,rawget(t,k.v)也是绕过__newindex元方法直接对table进行设置;