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. PHP异常处理函数set_exception_handler()的用法

    定义和用法 set_exception_handler() 函数设置用户自定义的异常处理函数. 该函数用于创建运行时期间的用户自己的异常处理方法. 该函数会返回旧的异常处理程序,若失败,则返回 nul ...

  2. PHP 获取中国时间,即上海时区时间

    /** * 获取中国时间,即上海时区时间 * @param <type> $format * @return <type> */ function getChinaTime($ ...

  3. Mac Pro 实现 PHP-5.6 与 PHP-7.0 等多版本切换

    先前参考 如何 实现PHP多版本的 共存 和 切换? 实现了Linux(Ubuntu/CentOS)系统下,PHP多版本的切换,但是在 Mac OS 下,由于用户权限控制的比较严格,文章里提到的脚本运 ...

  4. Javascript实现图片预加载【回调函数,多张图片】

    使用JS实现一组图片动画效果或者使用HTML5 Canvas渲染一系列图片等案例中,需要图片全部加载完成方可运行动画效果.此时程序中就会涉及多张图片预加载代码.当接二连三的案例中都涉及图片预加载时,就 ...

  5. Spring MVC+FreeMarker简介

    最近做项目,刚接触到SpringMVC与FreeMarker框架,就简单介绍一下自己的理解,不正确的地方请大家指教!! 1.Spring MVC工作原理: 用户发送请求--->前端服务器去找相对 ...

  6. C# mongodb 驱动操作(Z)

    Query.All("name", "a", "b");//通过多个元素来匹配数组 Query.And(Query.EQ("nam ...

  7. System Error Codes

    很明显,以下的文字来自微软MSDN 链接http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx M ...

  8. Python学习笔记(一)——环境搭建

    一.安装包下载: 国内镜像:32位:http://pan.baidu.com/s/1jI4q4lS        64位:http://pan.baidu.com/s/1eRPhpRW 版本更迭速度很 ...

  9. JavaScript(一)

    JavaScript 是脚本语言 JavaScript 是一种可插入 HTML 页面的轻量级的编程语言,它跟Java没有什么蛋关系. JavaScript使用: <script language ...

  10. BZOJ 2460 [BeiJing2011]元素 ——线性基

    [题目分析] 线性基,由于最多有63个,只需要排序之后,动态的去维护线性基即可. [代码] #include <cstdio> #include <cstring> #incl ...