lua的Metatables和Metamethods
2016-04-07 20:20
585 查看
Metatable:
lua中的每一个表都有其Metatable,默认情况下Metatable为nil。可通过setmetatable函数设置或者改变一个表的Metatable,
也可以通过getmetatable得到一个表的Metatable。任何一个表都可以是其它表的Metatable,可以多个表共享一个Metatable,
一个表也可以是自身的Metatable。
作用:使我们可以改变table的行为
在metatable中设置__add, __sub, __mul, __div, __eq(等于), __lt(小于), __le(小于等于), __unm(负), __pow(幂),
__concat (定义连接行为),__tostring等metamethod方法,可以实现类似于C++中运算符重载的效果。
实例:
当我们对两个有不同metatable的表进行加操作时,则检查第一个表的metatabled是否有__add,有则用之,
没有就再去检查第二个表。。。还没有就报错。
__index:
我们在访问一个表不存在的域时,lua解释器会去查找metatabled中是否有__index方法(metamethod),如果不存在则返回nil,
否则由__index方法返回。__index可以是函数也可以是表
__newindex:
当你给表不存在的值赋值时,lua解释器就会查找对应Metatable中的__newindex方法(metamethod)。如果存在则调用这个函数而不进行赋值。
rawset(t, k, v):
不调用任何的metamethod 对表t的k域赋值为v,上述例子就可以用rawset(myTb, "sex", "man")赋值。
给表设置默认值:
监控表:
index用于查询,__newindex用于更新,它们都是在访问的域不存在的时候才起作用。如果我们想捕获对一个表的所有反问,可以通过保持这个表为空来实现。
lua中的每一个表都有其Metatable,默认情况下Metatable为nil。可通过setmetatable函数设置或者改变一个表的Metatable,
也可以通过getmetatable得到一个表的Metatable。任何一个表都可以是其它表的Metatable,可以多个表共享一个Metatable,
一个表也可以是自身的Metatable。
作用:使我们可以改变table的行为
在metatable中设置__add, __sub, __mul, __div, __eq(等于), __lt(小于), __le(小于等于), __unm(负), __pow(幂),
__concat (定义连接行为),__tostring等metamethod方法,可以实现类似于C++中运算符重载的效果。
实例:
Set = {} Set.mt = {} --setmetatable(Set.mt, Set.mt) function Set:new( t ) local tb = t or {} setmetatable(tb, Set.mt) return tb end function Set.union( a, b ) local res = Set.new() for _, k in pairs(a) do table.insert(res, k) end for _, k in pairs(b) do table.insert(res, k) end return res end function Set.tostring( set ) local s = "{\n" local sep = " " for _, k in pairs(set) do if type(k) == "boolean" then k = "boolean" elseif type(k) == "function" then k = "function" elseif type(k) == "table" then -- k = "table" k = Set.tostring(k) end s = s.." [".._.."]".." = "..k.."\n" end return s.."}" end local s1 = Set:new({10, 20, 30, 50}) local s2 = Set:new({40, 60}) Set.mt.__add = Set.union Set.mt.__concat = Set.union Set.mt.__tostring = Set.tostring local s3 = s1 + s2 print(s3) local s4 = s1..s2 print(s4) 这里+和..是等价的,所以s3==s4,结果: { [1] = 10 [2] = 20 [3] = 30 [4] = 40 [5] = 50 [6] = 60 } { [1] = 10 [2] = 20 [3] = 30 [4] = 40 [5] = 50 [6] = 60 }
当我们对两个有不同metatable的表进行加操作时,则检查第一个表的metatabled是否有__add,有则用之,
没有就再去检查第二个表。。。还没有就报错。
__index:
我们在访问一个表不存在的域时,lua解释器会去查找metatabled中是否有__index方法(metamethod),如果不存在则返回nil,
否则由__index方法返回。__index可以是函数也可以是表
Set.mt.__index = function (tb, key)--这里会传进来一个table和key return "get "..key.." is null" end -- Set.mt.__index = {sex = "man"} local myTb = Set:new({name = "Mical", age = 12}) print(myTb.name) print(myTb.age) print(myTb.sex) 结果: Mical 12 get sex is null
__newindex:
当你给表不存在的值赋值时,lua解释器就会查找对应Metatable中的__newindex方法(metamethod)。如果存在则调用这个函数而不进行赋值。
Set.mt.__newindex = function (tb, key, val) print("can't set "..key.." value") end local myTb = Set:new({name = "Mical", age = 12}) myTb.sex = "man" 结果: can't set sex value
rawset(t, k, v):
不调用任何的metamethod 对表t的k域赋值为v,上述例子就可以用rawset(myTb, "sex", "man")赋值。
给表设置默认值:
local key = {} local mt = {__index = function(t) return t[key] end} function setDefault(t, d) t[key] = d setmetatable(t, mt) end
监控表:
index用于查询,__newindex用于更新,它们都是在访问的域不存在的时候才起作用。如果我们想捕获对一个表的所有反问,可以通过保持这个表为空来实现。
local index = {} local mt = { __index = function(t, k) print("access to element "..tostring(k)) return t[index][k] end, __newindex = function(t, k, v) print("update of element "..tostring(k).." to "..tostring(v)) t[index][k] = v end } local function track(t) local proxy = {} proxy[index] = t setmetatable(proxy, mt) return proxy end local myTb = {} local nowTb = track(myTb) nowTb.name = "mical" print(nowTb.name) nowTb.age = 12 print(nowTb.sex) for k, v in pairs(nowTb) do print(k, "\n", v); end
相关文章推荐
- lua脚本之lua语言简介以及lua的安装
- Lua学习笔记-习题9.3
- 云风的博文《Lua C API 的正确用法》读后总结
- evaluateScript--evaluatePopoverScript--区别
- Lua学习笔记-9.4章-非抢占式的多线程
- Lua学习笔记六——package
- LUA require 搜索路径指定方法
- ngx_lua访问数据库
- lua使用table.concat连接大量字符串
- lua探索--------------(_G相关)
- LuaSQLite3 搭建使用过程
- Lua学习教程之 可变參数数据打包与解包
- Programming in Lua
- 我和Lua并非一见钟情,我们期待着日久生情(相遇篇)
- Embedding LuaJIT in 30 minutes (or so)
- FFI Library (lua 调用 c)
- Lua求n的阶乘
- Lua协同程序
- 使用ngx_lua构建高并发应用(2)
- 使用ngx_lua构建高并发应用(1)