什么是Metatable

metatable是Lua中的重要概念,每一个table都可以加上metatable,以改变相应的table的行为。

Metatables举例

-- 声明一个正常的关系变量
lo_table = {} -- 声明空元表变量
lo_meta_table = {} -- 为关系变量t设置元表变量
setmetatable(lo_table, lo_meta_table) -- 获取一个关系变量的元表变量
getmetatable(lo_table)

上边的代码也可以写成一行,如下所示

-- setmetatable函数的返回值,就是该函数的第一个参数
lo_table = setmetatable({}, {})

创建复杂的元表变量

metatable可以包括任何东西,metatable特有的键一般以__开头,例如__index__newindex,它们的值一般是函数或其他table。

lo_table = setmetatable({}, {
__index = function(lo_table, key)
if key == "foo" then
return
else
return table[key]
end
end
})

__index

  这是metatable最常用的键了。

  当你通过键来访问table的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的__index键。如果__index包含一个表格,Lua会在表格中查找相应的键。

-- 创建元表变量
lo_meta_table = { name = "蓝鸥" } -- 设置该元表变量作为关系变量的
lo_table = setmetatable({}, { __index = lo_meta_table }) -- 打印lo_table变量的姓名 蓝鸥
print(lo_table.name) -- 打印lo_table变量年龄 nil
print(lo_table.age)

  如果__index包含一个函数的话,Lua就会调用那个函数,table和键会作为参数传递给函数。

-- 创建元表变量
lo_meta_table = {
name = "蓝鸥" ,
action = function ( param )
-- body
if(param == "学生") then
print("让教育回归本质")
else
print("让蓝鸥维护教育")
end
end
} -- 设置该元表变量作为关系变量的
lo_table = setmetatable({}, { __index = lo_meta_table }) -- 打印lo_table变量的动作 让教育回归本质
print(lo_table.action("学生")) -- 打印lo_table变量的动作 让蓝鸥维护教育
print(lo_table.action("肖浩")) -- 打印lo_table变量年龄 nil
print(lo_table.age)

__newindex

类似__index__newindex的值为函数或table,用于按键赋值的情况。

-- 创建元表变量
lo_meta_table = {} -- 设置该元表变量作为关系变量的
lo_table = setmetatable({}, { __newindex = lo_meta_table }) -- 设置lo_table变量的name关键字的值
lo_table.name = "蓝鸥" -- 打印lo_meta_table元表变量name关键字的值值
print(lo_meta_table.name) -- 打印lo_table变量name关键字的值
print(lo_table.name)
-- 创建元表变量
lo_meta_table = {} -- 设置该元表变量作为关系变量的
lo_table = setmetatable({}, { __newindex = function(t, key, value)
if type(value) == "number" then
rawset(t, key, value * value)
else
rawset(t, key, value)
end
end
}) -- 设置lo_table变量的name关键字的值
lo_table.name = "蓝鸥" -- 设置lo_table变量的age关键字的值
lo_table.age = -- 打印lo_meta_table元表变量name关键字的值值
print(lo_meta_table.name) -- 打印lo_table变量name关键字的值
print(lo_table.name) -- 打印lo_meta_table元表变量age关键字的值值
print(lo_meta_table.age) -- 打印lo_table变量age关键字的值
print(lo_table.age)

上面的代码中使用了rawgetrawset以避免死循环。使用这两个函数,可以避免Lua使用__index__newindex

运算符

利用metatable可以定义运算符,例如+

-- 创建重载+号行为的表变量
lo_table = setmetatable({ , , }, {
__add = function(lo_table, other)
new = {} -- 遍历元素加other
for _, v in ipairs(lo_table)
do table.insert(new, v + other)
end return new
end
}) -- 进行计算+
lo_table = lo_table + -- 打印得到的结果
print(lo_table[])
print(lo_table[])
print(lo_table[])

__index__newindex不同,__mul的值只能是函数。与__mul类似的键有:

  • __add (+)
  • __sub (-)
  • __div (/)
  • __mod (%)
  • __unm 取负
  • __concat (..)
  • __eq (==)
  • __lt (<)
  • __le (<=)

__call

__call使得你可以像调用函数一样调用table

t = setmetatable({}, {
__call = function(t, a, b, c, whatever)
return (a + b + c) * whatever
end
}) local result = t(, , , )
print(result)

__tostring

最后讲下__tostring,它可以定义如何将一个table转换成字符串,经常和 print 配合使用,因为默认情况下,你打印table的时候会显示 table: 0x7f86f3d04d80 这样的代码

lo_table = setmetatable({ , ,  }, {
__tostring = function(lo_table)
sum =
for _, v in pairs(lo_table)
do
sum = sum + v
end return "计算的结果是: " .. sum
end
}) -- prints out "计算的结果是: 6"
print(lo_table)

创建一个简单的向量Vector类

Vector = {}
Vector.__index = Vector function Vector.new(x, y)
return setmetatable({ x = x or , y = y or }, Vector)
end -- __call关键字
setmetatable(Vector, { __call = function(_, ...) return Vector.new(...) end }) -- + 运算符
function Vector:__add(other)
-- ...
local result = Vector(self.x + other.x,self.y + other.y) return result
end -- __tostring关键字
function Vector:__tostring()
-- body return "x: " .. self.x .. " y: " .. self.y end a = Vector.new(, )
b = Vector(, )
c = a + b print(a)
print(c)

原文链接:http://nova-fusion.com/2011/06/30/lua-metatables-tutorial/

[Lua]Lua高级教程Metatables的更多相关文章

  1. Lua高级教程Metatables

    什么是Metatable metatable是Lua中的重要概念,每一个table都可以加上metatable,以改变相应的table的行为. Metatables举例 -- 声明一个正常的关系变量 ...

  2. Lua学习高级篇

    Lua学习高级篇 之前已经说了很多,我目前的观点还是那样,在嵌入式脚本中,Lua是最优秀.最高效的,如果您有不同的观点,欢迎指正并讨论,切勿吐槽.这个系列完全来自于<Programming in ...

  3. ios cocopods 安装使用及高级教程

    CocoaPods简介 每种语言发展到一个阶段,就会出现相应的依赖管理工具,例如Java语言的Maven,nodejs的npm.随着iOS开发者的增多,业界也出现了为iOS程序提供依赖管理的工具,它的 ...

  4. 【读书笔记】.Net并行编程高级教程(二)-- 任务并行

    前面一篇提到例子都是数据并行,但这并不是并行化的唯一形式,在.Net4之前,必须要创建多个线程或者线程池来利用多核技术.现在只需要使用新的Task实例就可以通过更简单的代码解决命令式任务并行问题. 1 ...

  5. 【读书笔记】.Net并行编程高级教程--Parallel

    一直觉得自己对并发了解不够深入,特别是看了<代码整洁之道>觉得自己有必要好好学学并发编程,因为性能也是衡量代码整洁的一大标准.而且在<失控>这本书中也多次提到并发,不管是计算机 ...

  6. 分享25个新鲜出炉的 Photoshop 高级教程

    网络上众多优秀的 Photoshop 实例教程是提高 Photoshop 技能的最佳学习途径.今天,我向大家分享25个新鲜出炉的 Photoshop 高级教程,提高你的设计技巧,制作时尚的图片效果.这 ...

  7. [译] Closures in Lua - Lua中的闭包

    原文:(PDF) . 摘要 一等(first-class)函数是一种非常强大的语言结构,并且是函数式语言的基础特性.少数过程式语言由于其基于栈的实现,也支持一等函数.本文讨论了Lua 5.x用于实现一 ...

  8. 展讯NAND Flash高级教程【转】

    转自:http://wenku.baidu.com/view/d236e6727fd5360cba1adb9e.html 展讯NAND Flash高级教程

  9. Net并行编程高级教程--Parallel

    Net并行编程高级教程--Parallel 一直觉得自己对并发了解不够深入,特别是看了<代码整洁之道>觉得自己有必要好好学学并发编程,因为性能也是衡量代码整洁的一大标准.而且在<失控 ...

随机推荐

  1. 云信推送通知 APN invalid Token

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; color: #e4af09; min-height: 14.0px } ...

  2. 类加载class loader

    Class装载验证流程: 加载:取得类的二进制流,转为方法区的数据结构,在java堆中生成对应的java.lang.class对象 链接:就是将已经读入到内存的类的二进制数据合并到虚拟机的运行时环境中 ...

  3. 【HELLO WAKA】WAKA iOS客户端 之二 架构设计与实现篇

    上一篇主要做了MAKA APP的需求分析,功能结构分解,架构分析,API分析,API数据结构分析. 这篇主要讲如何从零做iOS应用架构. 全系列 [HELLO WAKA]WAKA iOS客户端 之一 ...

  4. 第一次使用cnblogs

    第一次使用!!!!!留名纪念下!!!!!!!!!!!

  5. linux中ssh登录Permanently added (RSA) to the list of known hosts问题解决

    文章出自http://www.2cto.com/os/201307/227199.html linux中ssh登录Permanently added (RSA) to the list of know ...

  6. SQLite学习网址

    http://www.runoob.com/sqlite/sqlite-data-types.html

  7. JavaScript 运动框架 Step by step(转)

    1,运动原理 Js运动,本质来说,就是让 web 上 DOM 元素动起来.而想要 DOM 动起来,改变其自身的位置属性,比如高宽,左边距,上边距,透明度等.动画的原理就是把不同状态的物体,串成连续的样 ...

  8. js实例--js滚动条缓慢滚动到顶部

    收集篇(已测)-- <html><head> <script type="text/javascript"> var currentPositi ...

  9. 数据库DateTime类型为空的处理

    一,写一个辅助类,将该方法设为静态,先装换为object,在转为DateTime,返回DateTime public class DateTimeHelper { public static Date ...

  10. 《JavaScript网页特效经典300例-进阶篇》

    <Javascript网页经典特性300例> 进阶篇 第11章:导航菜单特效 二级导航菜单三级导航菜单动态加载导航菜单三级联动导航菜单树形导航菜单当网页超过一屏时导航菜单始终置顶 第12章 ...