Lua 元表(Metatable)

在 Lua table 中我们可以访问对应的key来得到value值,但是却无法对两个 table 进行操作。

个人理解,这个相当于其他语言的继承,是把这个类的方法和属性塞进新的表里面。

因此 Lua 提供了元表(Metatable),允许我们改变table的行为,每个行为关联了对应的元方法。

例如,使用元表我们可以定义Lua如何计算两个table的相加操作a+b。

当Lua试图对两个表进行相加时,先检查两者之一是否有元表,之后检查是否有一个叫"__add"的字段,若找到,则调用对应的值。"__add"等即时字段,其对应的值(往往是一个函数或是table)就是"元方法"。

有两个很重要的函数来处理元表:

setmetatable(table,metatable): 对指定table设置元表(metatable),如果元表(metatable)中存在__metatable键值,setmetatable会失败 。

getmetatable(table): 返回对象的元表(metatable)。

以下实例演示了如何对指定的表设置元表:

__index参考示例

local a1 = { 20, 1, key1 = "hello_a1", key2 = "world_a1", lang = "lua" }
print("the table a1:")
for _, v in pairs(a1) do
print(v)
end --[输出结果]
--the table a1:
--20
--1
--hello_a1
--world_a1
--lua local a2 = {
key1 = "hello_a2",
key2 = "world_a2"
} print("the old table a2:")
for _, v in pairs(a2) do
print(v)
end --[输出结果]
--the table a2:
--hello_a2
--world_a2 print("a2的metatable:", getmetatable(a2))
print("language:", a2["lang"]) --[输出结果]
--a2的metatable: nil
--language: nil -- 关注函数及__index
setmetatable(a2, { __index = a1 }) print("the new table a2:")
for _, v in pairs(a2) do
print(v)
end --[输出结果]
--the new table a2:
--hello_a2
--world_a2 print("language:", a2["lang"]) --[输出结果]
--language: lua print("a2数组第一个元素:", a2[1])
print("a2的metatable:", getmetatable(a2)) --[输出结果]
--a2数组第一个元素: 20
--a2的metatable: table:0x5A8E6888

大家可以参考lua手册,metatable是被译作元表,Lua 中的每个值都可以用一个 metatable。这个 metatable 就是一个原始的 Lua table ,它用来定义原始值在特定操作下的行为。

一个 metatable 可以控制一个对象做数学运算操作、比较操作、连接操作、取长度操作、取下标操作时的行为,metatable 中还可以定义一个函数,让 userdata 作垃圾收集时调用它。对于这些操作,Lua 都将其关联上一个被称作事件的指定健。当 Lua 需要对一个值发起这些操作中的一个时,它会去检查值中 metatable 中是否有对应事件。如果有的话,键名对应的值(元方法)将控制 Lua 怎样做这个操作。

连接符对应的操作

metatable通过其包含的函数来给所挂接的table定义一些特殊的操作,包括:

__unm: 定义负操作, 即: -table的含义

__tostring: 定义当table作为tostring()函式之参数被呼叫时的行为(例如: print(table)时将呼叫tostring(table)作为输出结果)

__index: 定义当table中不存在的key值被试图获取时的行为

__newindex: 定义在table中产生新key值时的行为

模式 对应操作符 描述
__add 对应的运算符 '+' 定义所挂接table的加法操作
__sub 对应的运算符 '-' 定义减法操作
__mul 对应的运算符 '*' 定义乘法操作
__div 对应的运算符 '/' 定义除法操作
__mod 对应的运算符 '%' ...
__unm 对应的运算符 '-'(负) 定义负操作, 即: -table的含义
__concat 对应的运算符 '..' 定义连接操作(".."运算符)
__eq 对应的运算符 '==' ..
__lt 对应的运算符 '<'
__le 对应的运算符 '<='

__tostring参考示例

local table1 = {10, 20, 30}

local table2 = {}
table2.__tostring = function(myTable)
local sum = 0
for _, v in pairs(myTable) do
sum = sum + v
end
return ("表元素之和=" .. sum)
end setmetatable(table1, table2)
print(table1) --[输出结果]
--表元素之和=60

参考资料及推荐阅读

http://www.runoob.com/lua/lua-metatables.html
http://blog.csdn.net/eckelwei/article/details/9299899
http://www.cnblogs.com/JimLy-BUG/p/5364281.html

学习Lua setmetatable Lua 元表的更多相关文章

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

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

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

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

  3. Lua中的元表与元方法

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

  4. Lua中的元表和元方法

    Lua中每个值都可具有元表. 元表是普通的Lua表,定义了原始值在某些特定操作下的行为.你可通过在值的原表中设置特定的字段来改变作用于该值的操作的某些行为特征.例如,当数字值作为加法的操作数时,Lua ...

  5. uLua 学习笔记 之一 lua脚本 打包与读取

    最近要学习热更新,搜了下,选择了ulua这个插件,本人也是新人.对这个插件也是一知半解,不过幸好加了专门讨论这一块的群,这个群的技术氛围还是很浓重的,特别是已经形成了一套自己的lua学习框架.最近周末 ...

  6. Nginx详解二十二:Nginx深度学习篇之Lua解释器安装及基础语法

    解释器 Lua:Lua是一个简洁.轻量.可扩展的脚本语言 Nginx+Lua优势充分的结合Nginx的并发处理epoll优势的Lua的轻量实现简单的功能切高并发的场景 安装Lua 1.安装解释器:yu ...

  7. 优雅的使用sublime写lua~ sublime lua相关必装插件推荐~~

    缘起 lua脚本语言虽好,代码写得飞快,可是写错了调试起来却很困难,lua使用者经常容易犯得一个错误是--写错变量名了,if end 嵌套太多没匹配~,多打了一个逗号, 假设定义了一个变量 local ...

  8. [转]Lua和Lua JIT及优化指南

    一.什么是lua&luaJit lua(www.lua.org)其实就是为了嵌入其它应用程序而开发的一个脚本语言, luajit(www.luajit.org)是lua的一个Just-In-T ...

  9. This module embeds Lua, via LuaJIT 2.0/2.1, into Nginx and by leveraging Nginx's subrequests, allows the integration of the powerful Lua threads (Lua coroutines) into the Nginx event model.

    openresty/lua-nginx-module: Embed the Power of Lua into NGINX HTTP servers https://github.com/openre ...

随机推荐

  1. CSharpGL(47)你好,Framebuffer!

    CSharpGL(47)你好,Framebuffer! Framebuffer对象(FBO)是一种复杂的OpenGL对象.使用自定义的framebuffer,可以实现离屏渲染,进而实现很多高级功能,例 ...

  2. Kaggle实战之二分类问题

    0. 前言 1. MNIST 数据集 2. 二分类器 3. 效果评测 4. 多分类器与误差分析 5. Kaggle 实战 0. 前言 "尽管新技术新算法层出不穷,但是掌握好基础算法就能解决手 ...

  3. 【Android开发学习笔记之一】5大布局方式详解

    Android中常用的5大布局方式有以下几种: 线性布局(LinearLayout):按照垂直或者水平方向布局的组件. 帧布局(FrameLayout):组件从屏幕左上方布局组件. 表格布局(Tabl ...

  4. Less的!important关键字

    Less的!important关键字 在调用 mixin 时,如果在后面追加 !important 关键字,就可以将 mixin 里面的所有属性都标记为 !important.如,以下Less代码: ...

  5. hotspot虚拟机的调试

    3这篇文章,怎么说呢.是踩了很多坑得出来了,也是在自己快要崩溃的时候得出来了的. 连续踩了差不多10来个小时的坑,还好是出来了. 这篇文章是调试虚拟机的,其实网上也能找到一些文章,但是每个人的环境不一 ...

  6. Emrips 反质数枚举 javascript实现

    今天看到一个kata,提出一个"emirps"的概念:一个质数倒转后得到的是一个不同的质数,这个数叫做"emirps". 例如:13,17是质数,31,71也是 ...

  7. Spring MVC 学习总结(九)——Spring MVC实现RESTful与JSON(Spring MVC为前端提供服务)

    很多时候前端都需要调用后台服务实现交互功能,常见的数据交换格式多是JSON或XML,这里主要讲解Spring MVC为前端提供JSON格式的数据并实现与前台交互.RESTful则是一种软件架构风格.设 ...

  8. UnityShader-菲涅尔反射(Fresnel Reflection)

    菲涅耳公式(或菲涅耳方程),由奥古斯丁·让·菲涅耳导出.用来描述光在不同折射率的介质之间的行为.由公式推导出的光的反射称之为"菲涅尔反射".菲涅尔公式是光学中的重要公式,用它能解释 ...

  9. SQL Server 日志清理

    --SQL2005: Backup Log DNName with no_log --这里的DNName是你要收缩的数据库名,自己注意修改下面的数据库名,我就不再注释了. go dump transa ...

  10. jvm内存回收诡异现象

    在知乎上看到一篇提问,于是做了个实验帮助他解答,这里整理成一篇文章分享一下. 先看代码如下代码: /** * Created on 2017/12/16. * * -verbose:gc -XX:+U ...