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++中运算符重载的效果。

实例:

 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({, , , })
local s2 = Set:new({, }) 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,结果:
{
[] =
[] =
[] =
[] =
[] =
[] =
}
{
[] =
[] =
[] =
[] =
[] =
[] =
}

  当我们对两个有不同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 = })
print(myTb.name)
print(myTb.age)
print(myTb.sex) 结果:
Mical 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 = })
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 =
print(nowTb.sex) for k, v in pairs(nowTb) do
print(k, "\n", v);
end

lua的Metatables和Metamethods的更多相关文章

  1. Lua 与 Redis

    Lua 与 Redis 标签: Java与NoSQL 从 2.6版本 起, Redis 开始支持 Lua 脚本 让开发者自己扩展 Redis - 案例-实现访问频率限制: 实现访问者 $ip 在一定的 ...

  2. [转]LUA元表

    lua元表和元方法 <lua程序设计> 13章 读书笔记 lua中每个值都有一个元表,talble和userdata可以有各自独立的元表,而其它类型的值则共享其类型所属的单一元表.lua在 ...

  3. Lua.LearningLua.7-userdata

    Learning Lua: 7 - userdata 1. Userdata basic "There are eight basic types in Lua: nil, boolean, ...

  4. 初识lua

    转自:http://www.oschina.net/question/12_115993-- 两个横线是单行注释(译者注:这跟 SQL 一样) --[[ 增加两个 [ 和 ] 变成多行注释 我是多行注 ...

  5. lua学习

    在lua中,一切都是变量,除了关键字. 1.注释: 单行注释: 连续两个减号“--”表示注释的开始,一直延续到行末.相当于C语言中的“//” 多行注释:由“--[[”表示注释开始, “]]”表示注释结 ...

  6. Lua语言模型 与 Redis应用

    Lua语言模型 与 Redis应用 标签: Java与NoSQL 从 2.6版本 起, Redis 开始支持 Lua 脚本 让开发者自己扩展 Redis. 本篇博客主要介绍了 Lua 语言不一样的设计 ...

  7. Learn Lua in 15 Minutes

    原文地址:http://tylerneylon.com/a/learn-lua/ Learn Lua in 15 Minutes more or less For a more in-depth Lu ...

  8. Redis结合Lua脚本实现高并发原子性操作

    从 2.6版本 起, Redis 开始支持 Lua 脚本 让开发者自己扩展 Redis … 案例-实现访问频率限制: 实现访问者 $ip 在一定的时间 $time 内只能访问 $limit 次. 非脚 ...

  9. 15分钟入门lua

    目录:[ - ] -- 1. Variables and flow control. -- 2. Functions. -- 3. Tables. -- 3.1 Metatables and meta ...

随机推荐

  1. Lazarus开发环境编译选项配置

    Lazarus的环境配置让人有点犯晕,对于刚从delphi转到lazarus上的我来说,每次新建工程都会遇到一堆Can't find unit xxxx used by xxxx的问题,问题虽然不大, ...

  2. PJAX全局无刷新的设置方法~

    先添加必要文件: <script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></scrip ...

  3. Swift库二进制接口(ABI)兼容性研究

    前言 阿里云APP组件化过程中,我们拆分出了若干基础组件库和业务代码库,由于代码是采用Swift编写的,所以这些库都是动态库形式.在上一个正式版本,组件化达到了完全形态,主工程只剩下一个壳,所有代码都 ...

  4. 在Ubuntu环境下搭建esp32开发环境

    第一步:下载必要的库文件   sudo apt-get install git make gcc libncurses5-dev flex bison gperf python-serial     ...

  5. 【剑指Offer】8、跳台阶

      题目描述:   一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果).   解题思路:   首先考虑最简单的情况,如果只有1级台阶, ...

  6. HTTP 状态码之:301、302 重定向

    转自:http://www.cnblogs.com/5207/p/5908354.html 概念 301 Moved Permanently 被请求的资源已永久移动到新位置,并且将来任何对此资源的引用 ...

  7. 洛谷P1060 开心的金明【dp】

    金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:"你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过NN元钱就行&qu ...

  8. python类中属性逗号引发的类型改变

    不注意点了个逗号引发了类型改变 [shangbl@newsvn ~]$ cat test.py class AB1: a="a" class AB12: a="a&quo ...

  9. C#学习笔记_04_流程控制

    04_流程控制 程序的执行结构: 顺序结构 分支结构 循环结构 可以通过某些特定的控制语句来控制代码的执行结构 分支流程控制 if else 基本语法 可以只有if没有else,但是不能没有if只有e ...

  10. 洛谷 P1595 信封问题

    题目描述 某人写了n封信和n个信封,如果所有的信都装错了信封.求所有信都装错信封共有多少种不同情况. 输入输出格式 输入格式: 一个信封数n 输出格式: 一个整数,代表有多少种情况. 输入输出样例 输 ...