文档章节

lua中metatables和metamethods

andrew810810
 andrew810810
发布于 2017/02/17 14:37
字数 2214
阅读 29
收藏 0
点赞 0
评论 0
Lua

reference:

http://www.lua.org/manual/5.3/manual.html

 

2.4 – Metatables and Metamethods

Every value in Lua can have a metatable. This metatable is an ordinary Lua table that defines the behavior of the original value under certain special operations. You can change several aspects of the behavior of operations over a value by setting specific fields in its metatable. For instance, when a non-numeric value is the operand of an addition, Lua checks for a function in the field "__add" of the value's metatable. If it finds one, Lua calls this function to perform the addition.

The key for each event in a metatable is a string with the event name prefixed by two underscores; the corresponding values are called metamethods. In the previous example, the key is "__add" and the metamethod is the function that performs the addition.

You can query the metatable of any value using the getmetatable function. Lua queries metamethods in metatables using a raw access (see rawget). So, to retrieve the metamethod for event ev in object o, Lua does the equivalent to the following code:

rawget(getmetatable(o) or {}, "__ev")

You can replace the metatable of tables using the setmetatable function. You cannot change the metatable of other types from Lua code (except by using the debug library (§6.10)); you should use the C API for that.

Tables and full userdata have individual metatables (although multiple tables and userdata can share their metatables). Values of all other types share one single metatable per type; that is, there is one single metatable for all numbers, one for all strings, etc. By default, a value has no metatable, but the string library sets a metatable for the string type (see §6.4).

A metatable controls how an object behaves in arithmetic operations, bitwise operations, order comparisons, concatenation, length operation, calls, and indexing. A metatable also can define a function to be called when a userdata or a table is garbage collected (§2.5).

For the unary operators (negation, length, and bitwise NOT), the metamethod is computed and called with a dummy second operand, equal to the first one. This extra operand is only to simplify Lua's internals (by making these operators behave like a binary operation) and may be removed in future versions. (For most uses this extra operand is irrelevant.)

A detailed list of events controlled by metatables is given next. Each operation is identified by its corresponding key.

  • __addthe addition (+) operation. If any operand for an addition is not a number (nor a string coercible to a number), Lua will try to call a metamethod. First, Lua will check the first operand (even if it is valid). If that operand does not define a metamethod for __add, then Lua will check the second operand. If Lua can find a metamethod, it calls the metamethod with the two operands as arguments, and the result of the call (adjusted to one value) is the result of the operation. Otherwise, it raises an error.
  • __subthe subtraction (-) operation. Behavior similar to the addition operation.
  • __multhe multiplication (*) operation. Behavior similar to the addition operation.
  • __divthe division (/) operation. Behavior similar to the addition operation.
  • __modthe modulo (%) operation. Behavior similar to the addition operation.
  • __powthe exponentiation (^) operation. Behavior similar to the addition operation.
  • __unmthe negation (unary -) operation. Behavior similar to the addition operation.
  • __idivthe floor division (//) operation. Behavior similar to the addition operation.
  • __bandthe bitwise AND (&) operation. Behavior similar to the addition operation, except that Lua will try a metamethod if any operand is neither an integer nor a value coercible to an integer (see §3.4.3).
  • __borthe bitwise OR (|) operation. Behavior similar to the bitwise AND operation.
  • __bxorthe bitwise exclusive OR (binary ~) operation. Behavior similar to the bitwise AND operation.
  • __bnotthe bitwise NOT (unary ~) operation. Behavior similar to the bitwise AND operation.
  • __shlthe bitwise left shift (<<) operation. Behavior similar to the bitwise AND operation.
  • __shrthe bitwise right shift (>>) operation. Behavior similar to the bitwise AND operation.
  • __concatthe concatenation (..) operation. Behavior similar to the addition operation, except that Lua will try a metamethod if any operand is neither a string nor a number (which is always coercible to a string).
  • __lenthe length (#) operation. If the object is not a string, Lua will try its metamethod. If there is a metamethod, Lua calls it with the object as argument, and the result of the call (always adjusted to one value) is the result of the operation. If there is no metamethod but the object is a table, then Lua uses the table length operation (see §3.4.7). Otherwise, Lua raises an error.
  • __eqthe equal (==) operation. Behavior similar to the addition operation, except that Lua will try a metamethod only when the values being compared are either both tables or both full userdata and they are not primitively equal. The result of the call is always converted to a boolean.
  • __ltthe less than (<) operation. Behavior similar to the addition operation, except that Lua will try a metamethod only when the values being compared are neither both numbers nor both strings. The result of the call is always converted to a boolean.
  • __lethe less equal (<=) operation. Unlike other operations, the less-equal operation can use two different events. First, Lua looks for the __lemetamethod in both operands, like in the less than operation. If it cannot find such a metamethod, then it will try the __lt metamethod, assuming that a <= b is equivalent to not (b < a). As with the other comparison operators, the result is always a boolean. (This use of the __lt event can be removed in future versions; it is also slower than a real __le metamethod.)
  • __indexThe indexing access table[key]. This event happens when table is not a table or when key is not present in table. The metamethod is looked up in table.

    Despite the name, the metamethod for this event can be either a function or a table. If it is a function, it is called with table and key as arguments, and the result of the call (adjusted to one value) is the result of the operation. If it is a table, the final result is the result of indexing this table with key. (This indexing is regular, not raw, and therefore can trigger another metamethod.)

  • __newindexThe indexing assignment table[key] = value. Like the index event, this event happens when table is not a table or when key is not present in table. The metamethod is looked up in table.

    Like with indexing, the metamethod for this event can be either a function or a table. If it is a function, it is called with tablekey, and value as arguments. If it is a table, Lua does an indexing assignment to this table with the same key and value. (This assignment is regular, not raw, and therefore can trigger another metamethod.)

    Whenever there is a __newindex metamethod, Lua does not perform the primitive assignment. (If necessary, the metamethod itself can call rawset to do the assignment.)

  • __callThe call operation func(args). This event happens when Lua tries to call a non-function value (that is, func is not a function). The metamethod is looked up in func. If present, the metamethod is called with func as its first argument, followed by the arguments of the original call (args). All results of the call are the result of the operation. (This is the only metamethod that allows multiple results.)

It is a good practice to add all needed metamethods to a table before setting it as a metatable of some object. In particular, the __gc metamethod works only when this order is followed (see §2.5.1).

Because metatables are regular tables, they can contain arbitrary fields, not only the event names defined above. Some functions in the standard library (e.g.,tostring) use other fields in metatables for their own purposes.

getmetatable (object)

If object does not have a metatable, returns nil. Otherwise, if the object's metatable has a __metatable field, returns the associated value. Otherwise, returns the metatable of the given object.

setmetatable (table, metatable)

Sets the metatable for the given table. (To change the metatable of other types from Lua code, you must use the debug library (§6.10).) If metatable is nil, removes the metatable of the given table. If the original metatable has a __metatable field, raises an error.

This function returns table.

 

 

reference:

http://www.cnblogs.com/simonw/archive/2007/01/17/622032.html

什么是Metatable 

      Lua中Metatable这个概念, 国内将他翻译为元表. 元表为重定义Lua中任意一个对象(值)的默认行为提供了一种公开入口. 如同许多OO语言的操作符重载或方法重载. Metatable能够为我们带来非常灵活的编程方式. 

      具体的说, Lua中每种类型的值都有都有他的默认操作方式, 如, 数字可以做加减乘除等操作, 字符串可以做连接操作, 函数可以做调用操作, 表可以做表项的取值赋值操作. 他们都遵循这些操作的默认逻辑执行, 而这些操作可以通过Metatable来改变. 如, 你可以定义2个表如何相加等. 
      看一个最简单的例子, 重定义了2个表的加法操作. 这个例子中将c的__add域改写后将a的Metatable设置为c, 当执行到加法的操作时, Lua首先会检查a是否有Metatable并且Metatable中是否存在__add域, 如果有则调用, 否则将检查b的条件(和a相同), 如果都没有则调用默认加法运算, 而table没有定义默认加法运算, 则会报错.

示例1:

--定义2个表
a = {5, 6}
b = {7, 8}
--用c来做Metatable
c = {}
--重定义加法操作
c.__add = function(op1, op2)
   for _, item in ipairs(op2) do
      table.insert(op1, item)
   end
   return op1
end
--将a的Metatable设置为c
setmetatable(a, c)
--d现在的样子是{5,6,7,8}
d = a + b
print(d[1],d[2],d[3],d[4])

执行结果:

5	6	7	8

示例2:

a = {5, 6}
b = {7, 8}
--用c来做Metatable
c = {}
setmetatable(a, c)
d = a + b 

print(d[0], d[1],d[2],d[3],d[4],d[5])

执行结果:

lua: metatable.lua:57: attempt to perform arithmetic on global 'a' (a table value)
stack traceback:
	metatable.lua:57: in main chunk
	[C]: ?

这是由于Metatable中是不存在__add域,,而且table没有定义默认加法运算, 所以会报错.

 

Metatable并不神秘, 他只是一个普通的table, 在table这个数据结构当中, Lua定义了许多重定义这些操作的入口. 他们均以双下划线开头为table的域, 如上面例子的__add. 当你为一个值设置了Metatable, 并在Metatable中设置了重写了相应的操作域, 在这个值执行这个操作的时候就会触发重写的自定义操作. 当然每个操作都有每个操作的方法格式签名, 如__add会将加号两边的两个操作数做为参数传入并且要求一个返回值. 有人把这样的行为比作事件, 当xx行为触发会激活事件自定义操作.

Metatable中定义的操作add, sub, mul, div, mod, pow, unm, concat, len, eq, lt, le, tostring, gc, index, newindex, call...

      在Lua中任何一个值都有Metatable, 不同的值可以有不同的Metatable也可以共享同样的Metatable, 但在Lua本身提供的功能中, 不允许你改变除了table类型值外的任何其他类型值的Metatable, 除非使用C扩展或其他库. setmetatable和getmetatable是唯一一组操作table类型的Metatable的方法.

 

© 著作权归作者所有

共有 人打赏支持
andrew810810
粉丝 3
博文 127
码字总数 117648
作品 0
朝阳
Lua一系列很好的技术分享文章链接: 快速掌握 Lua 5.3

Lua一系列很好的技术分享文章链接: 快速掌握 Lua 5.3 --- 该系列文章作者: VermillionTear 作者博客专栏: 快速掌握Lua 5.3(http://blog.csdn.net/column/details/quicklymasterlua5-3.html)...

FreeBlues ⋅ 2016/05/29 ⋅ 2

Lua 5.3.0 正式版发布

经过 4 个 RC 版本,Lua 终于迎来了 5.3.0 正式版。新版本主要增加对整数支持,支持位操作,提供一个基本的 UTF-8 库。 下载地址:http://www.lua.org/ftp/lua-5.3.0.tar.gz 其他方面的改进包...

oschina ⋅ 2015/01/13 ⋅ 26

Lua 5.3.0 (beta) 发布

Lua 5.3.0 (beta) 发布,此版本现已提供测试:http://www.lua.org/work/lua-5.3.0-beta.tar.gz。 MD5 e46b91de3d22a308d3350a14b242e2c7 - SHA1 0fa2b527611fe3a1b083359ce15e91f27b108eec -......

oschina ⋅ 2014/10/25 ⋅ 10

Lua学习总结

简述 Lua是一个很小的编程语言,很多人将其与Python高级语言进行比较。 Lua有以下的特点: (1)纯C语言实现,源码小,可以很好地与C/C++融合。可自行编译,生成静态库。 (2)语法简单,灵活...

临峰不畏 ⋅ 2013/10/08 ⋅ 0

【Lua高级教程】什么是Metatable举例说明

什么是Metatable metatable是Lua中的重要概念,每一个table都可以加上metatable,以改变相应的table的行为。 Metatables举例 lotable =lometatable =(lotable) 上边的代码也可以写成一行,如...

浩浩老师 ⋅ 2015/09/08 ⋅ 0

[Lua]Lua高级教程Metatables

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

浩浩老师 ⋅ 2015/10/20 ⋅ 0

Why statement return error in current Lua(Codea)?

Why statement "table.insert(touches, touch.id, touch)" return error in current Lua(Codea)? Introduction When I tried to run some Codea code on the new version, I found that some......

FreeBlues ⋅ 2016/05/27 ⋅ 0

Lua(Codea) 中 table.insert 越界错误原因分析

Lua(Codea) 中 table.insert(touches, touch.id, touch) 越界错误原因分析 背景介绍 在 上运行其他人以前写的代码时, 发现某段处理 事件的代码总是报错, 开始报浮点数没有整型的表示, 修改代...

FreeBlues ⋅ 2016/05/27 ⋅ 0

Lua 语言模型与 Redis 应用

原文出处:朱吉芳 从 2.6 版本起,Redis 开始支持 Lua 脚本,可以让开发者自己扩展 Redis。本文主要介绍了 Lua 语言不一样的设计模型(相比于Java/C/C++、JS、PHP),以及 Redis 对 Lua 的扩展...

朱吉芳 ⋅ 2016/10/09 ⋅ 0

millken/ljsyscall

Unix system calls for LuaJIT What? An FFI implementation of the Linux kernel ABI for LuaJIT. This means you will be able to program all the functionality the Linux kernel provid......

millken ⋅ 2015/02/11 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

如何优雅的编程——C语言界面的一点小建议

我们鼓励在编程时应有清晰的哲学思维,而不是给予硬性规则。我并不希望你们能认可所有的东西,因为它们只是观点,观点会随着时间的变化而变化。可是,如果不是直到现在把它们写在纸上,长久以...

柳猫 ⋅ 31分钟前 ⋅ 0

从零手写 IOC容器

概述 IOC (Inversion of Control) 控制反转。熟悉Spring的应该都知道。那么具体是怎么实现的呢?下面我们通过一个例子说明。 1. Component注解定义 package cn.com.qunar.annotation;impo...

轨迹_ ⋅ 31分钟前 ⋅ 0

系统健康检查利器-Spring Boot-Actuator

前言 实例由于出现故障、部署或自动缩放的情况,会进行持续启动、重新启动或停止操作。它可能导致它们暂时或永久不可用。为避免问题,您的负载均衡器应该从路由中跳过不健康的实例,因为它们...

harries ⋅ 33分钟前 ⋅ 0

手把手教你搭建vue-cli脚手架-详细步骤图文解析[vue入门]

写在前面: 使用 vue-cli 可以快速创建 vue 项目,vue-cli很好用,但是在最初搭建环境安装vue-cli及相关内容的时候,对一些人来说是很头疼的一件事情,本人在搭建vue-cli的项目环境的时候也是...

韦姣敏 ⋅ 43分钟前 ⋅ 0

12c rman中输入sql命令

12c之前版本,要在rman中执行sql语句,必须使用sql "alter system switch logfile"; 而在12c版本中,可以支持大量的sql语句了: 比如: C:\Users\zhengquan>rman target / 恢复管理器: Release 1...

tututu_jiang ⋅ 57分钟前 ⋅ 0

Nginx的https配置记录以及http强制跳转到https的方法梳理

Nginx的https配置记录以及http强制跳转到https的方法梳理 一、Nginx安装(略) 安装的时候需要注意加上 --with-httpsslmodule,因为httpsslmodule不属于Nginx的基本模块。 Nginx安装方法: ...

Yomut ⋅ 今天 ⋅ 0

SpringCloud Feign 传递复杂参数对象需要注意的地方

1.传递复杂参数对象需要用Post,另外需要注意,Feign不支持使用GetMapping 和PostMapping @RequestMapping(value="user/save",method=RequestMethod.POST) 2.在传递的过程中,复杂对象使用...

@林文龙 ⋅ 今天 ⋅ 0

如何显示 word 左侧目录大纲

打开word说明文档,如下图,我们发现左侧根本就没有目录,给我们带来很大的阅读障碍 2 在word文档的头部菜单栏中,切换到”视图“选项卡 3 然后勾选“导航窗格”选项 4 我们会惊奇的发现左侧...

二营长意大利炮 ⋅ 今天 ⋅ 0

智能合约编程语言Solidity之线上开发工具

工具地址:https://ethereum.github.io/browser-solidity/ 实例实验: 1.创建hello.sol文件 2.调试输出结果

硅谷课堂 ⋅ 今天 ⋅ 0

ffmpeg 视频格式转换

转 Mp4 格式 #> ffmpeg -i input.avi -c:v libx264 output.mp4#> ffmpeg -i input.avi -c:v libx264 -strict -2 output.mp4#> ffmpeg -i input.avi -c:v libx264 -strict -2 -s 1......

Contac ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部