lua中提供的元表(metatable)与元方法(metamethod)是一种非常重要的语法,metatable主要用于做一些类似于C++重载操作符式的功能。

lua中提供的元表是用于帮助lua变量完成某些非预定义功能的个性化行为,如两个table的相加,通过让两者指向同一元表并修改该元表的元方法可以实现该功能。

任何table都可以成为任何值的元表,而一组相关的table也可以共享一个元表。

一些MetaMethod:

__add(a, b)                     对应表达式 a + b
__sub(a, b) 对应表达式 a - b
__mul(a, b) 对应表达式 a * b
__div(a, b) 对应表达式 a / b
__mod(a, b) 对应表达式 a % b
__pow(a, b) 对应表达式 a ^ b
__unm(a) 对应表达式 -a
__concat(a, b) 对应表达式 a .. b
__len(a) 对应表达式 #a
__eq(a, b) 对应表达式 a == b
__lt(a, b) 对应表达式 a < b
__le(a, b) 对应表达式 a <= b
__index(a, b) 对应表达式 a.b
__newindex(a, b, c) 对应表达式 a.b = c
__call(a, ...) 对应表达式 a(...)

1、算术类and关系类元方法

先看一个简单的例子:

--我们想让两个分数相加,这是一种非预定义的行为

fraction_a = {numerator=, denominator=}
fraction_b = {numerator=, denominator=}
fraction_op={} --元表 -- __add这是metatable,这是lua内建约定的
function fraction_op.__add(a,b)
res={}
res.numerator=a.numerator*b.denominator+b.numerator*a.denominator
res.denominator=a.denominator*b.denominator
return res
end --将fraction_a,fraction_b的元表设置为fraction_op
--其中setmetatable是库函数
setmetatable(fraction_a,fraction_op)
setmetatable(fraction_b,fraction_op) --调用的是fraction_op.__add()函数
fraction_c=fraction_a+fraction_b
print(fraction_c.numerator.."/"..fraction_c.denominator)
--输出结果
--26/21

再来看一个深度一点的例子,例举了算数类的元方法,关系类的元方法,库定义的元方法。

Set={}

local metatable={}  --元表

--根据参数列表中的值创建一个新的集合
function Set.new(a)
local set={}
--将所有由该方法创建的集合的元表都指定到metatable
setmetatable(set,metatable)
for i,v in pairs(a) do
set[v]=true
end
return set
end --计算两个集合的并集
function Set.union(a,b)
local res=Set.new{}
for i in pairs(a) do
res[i]=true
end
for i in pairs(b) do
res[i]=true
end
return res
end --计算两个集合的交集
function Set.intersect(a,b)
local res=Set.new{}
for i in pairs(a) do
res[i]=b[i]
end
return res
end --print总是调用tostring来格式化输出
--这里我们稍作修改库定义的print
function Set.tostring(a)
local t={}
for i in pairs(a) do
t[#t+]=i
end
return "{"..table.concat(t,",").."}"
end --判断a集合是否是b集合的子集
function Set.lessorequal(a,b)
for i in pairs(a) do
if not b[i] then return false end
end
return true
end --最后将重定向的元方法加入到元表中
metatable.__add=Set.union
metatable.__mul=Set.intersect
metatable.__tostring=Set.tostring
metatable.__le=Set.lessorequal
metatable.__eq=function(a,b) return a<=b and b<=a end
metatable.__lt=function(a,b) return a<=b and not (b<=a) end s1=Set.new{,,,}
s2=Set.new{,,}
s3=s1+s2
s4=s1*s2
print(s3)
print(s4)
print(+,*) --新加的方法不改变表本身具有的方法,因为传入的参数不同,只会让元方法更完善
s5=Set.new{,}
s6=Set.new{,,}
print(s5<=s6)
print(s5<s6)
print(s5==s6)
--输出结果
--{2,8,4,9,7}
--{2,4}
--7 12
--true
--true
--false

2、table访问的元方法:

算数类和关系类的元方法都为各自错误情况定义了行为,他们不会改变语言的常规行为,但lua还是提供了一种可以改变table的行为。有两种可以改变table的行为:查询table以及修改table中不存在的字段。

1)、__index元方法

当访问table中不存在的字段时,得到的结果为nil。如果我们为table定义了元方法__index,那访问的结果将由该方法决定。

Window={}
Window.prototype={x=,y=,width=,height=}
Window.mt={} --Window的元表 function Window.new(o)
setmetatable(o,Window.mt)
return o
end Window.mt.__index=function(table,key) return Window.prototype[key] end w=Window.new{x=,y=}
print(w.width)
print(w.width1)
--输出结果
--
--nil

2)、__newindex元方法

和__index不同的是,该元方法用于不存在键的赋值,而前者用于访问。

Window={}
Window.prototype={x=,y=,width=,height=}
Window.mt={} --Window的元表 function Window.new(o)
setmetatable(o,Window.mt)
return o
end Window.mt.__index=function(table,key) return Window.prototype[key] end
Window.mt.__newindex=function(table,key,value) Window.prototype[key]=value end w=Window.new{x=,y=}
w.length=
print(w.width)
print(w.width1)
print(Window.prototype.length)
--输出结果
--
--nil
--

lua元表与元方法的更多相关文章

  1. Step By Step(Lua元表与元方法)

    Step By Step(Lua元表与元方法) Lua中提供的元表是用于帮助Lua数据变量完成某些非预定义功能的个性化行为,如两个table的相加.假设a和b都是table,通过元表可以定义如何计算表 ...

  2. lua——元表、元方法、继承

    [元表] 元表中的键为事件(event),称值为元方法(metamethod). 通过函数getmetatable查询不论什么值的元表,通过函数setmetatable替换表的元表. setmetat ...

  3. lua元表和元方法 《lua程序设计》 13章 读书笔记

    lua中每个值都有一个元表,talble和userdata可以有各自独立的元表,而其它类型的值则共享其类型所属的单一元表.lua在创建table时不会创建元表. t = {} print(getmet ...

  4. lua 元表与元方法示例

    -- 1.检查是否有元表local t = {1, 2}print(getmetatable(t))     -- nilprint("----------------------" ...

  5. Lua 学习笔记(十一)元表与元方法

    在Lua中的每个值都有一套预定义的操作集合.例如可以将数字相加,可以连接字符串,还可以在table中插入一对key-value等.但是我们无法将两个table相加,无法对函数作比较,也无法调用一个字符 ...

  6. lua中 table 元表中元方法的重构实现

    转载请标明出处http://www.cnblogs.com/zblade/ lua作为游戏的热更新首选的脚本,其优势不再过多的赘述.今天,我主要写一下如何重写lua中的元方法,通过自己的重写来实现对l ...

  7. 【游戏开发】小白学Lua——从Lua查找表元素的过程看元表、元方法

    引言 在上篇博客中,我们简单地学习了一下Lua的基本语法.其实在Lua中有一个还有一个叫元表的概念,不得不着重地探讨一下.元表在实际地开发中,也是会被极大程度地所使用到.本篇博客,就让我们从Lua查找 ...

  8. lua编程之元表与元方法

    一. 前言 lua是一种非常轻量的动态类型语言,在1993年由由Roberto Ierusalimschy.Waldemar Celes 和 Luiz Henrique de Figueiredo等人 ...

  9. Lua中的元表与元方法学习总结

    前言 元表对应的英文是metatable,元方法是metamethod.我们都知道,在C++中,两个类是无法直接相加的,但是,如果你重载了"+"符号,就可以进行类的加法运算.在Lu ...

随机推荐

  1. Git 常用命令合集

    $ git init          建立git仓库(一般都是在github上新建好,直接克隆到本地) $ git clone **.git       克隆git仓库 $ git add -A   ...

  2. 百度地图用ip获取当前位置的经纬度(高精度)

    步骤比较简单先上百度地图API官网,申请一个应用AK(访问凭据):查看一下高进度定位的API,看看是否都符合要求下面直接上代码 /** * 根据ip获取地理坐标 * @param ip * @retu ...

  3. JQ图片轮播

    <script src="{staticurl action="jquery.js" type="js"}"></scri ...

  4. ACM/ICPC 之 Dinic算法(POJ2112)

    Optimal Milking //二分枚举最大距离的最小值+Floyd找到最短路+Dinic算法 //参考图论算法书,并对BFS构建层次网络算法进行改进 //Time:157Ms Memory:65 ...

  5. sqlserver中判断表或临时表是否存在

    转自:http://www.cnblogs.com/yugen/archive/2010/07/25/1784749.html 1.判断数据表是否存在 方法一: use yourdb;go if ob ...

  6. 技术架构:IBatisNet

    --连接数据库框架 1        providers.config 提供配制 常用的数据库连接程序 的xml文件 2        SqlMap.xml  SQL语句执行结果和实体对象之间的映射文 ...

  7. Bravebeart

    E - Bravebeart Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Sub ...

  8. oracle中lead和lag函数 (转载)

    解决上一户和下一户问题这两个函数,是偏移量函数,其用途是:可以查出同一字段下一个值或上一个值. lead(col_name,num,flag) col_name是列名:num是取向下第几个值:flag ...

  9. vue-cli构建vue项目

    参考资料:Vue2.0 新手完全填坑攻略—从环境搭建到发布 1.Node.js安装 https://nodejs.org/en/download/ 2.安装vue-cli npm install -g ...

  10. 会话控制:Cookie和session

    HTTP(超文本传输协议)定义了通过万维网(WWW)传输文本.图形.视频和所有其他数据所有的规则.HTTP是一种无状态的协议,说明每次请求的处理都与之前或之后的请求无关.虽然这种简化实现对于HTTP的 ...