文档章节

[Lua]Lua高级教程Metatables

浩浩老师
 浩浩老师
发布于 2015/10/20 14:15
字数 1041
阅读 29
收藏 3

什么是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 0 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 = 3 -- 打印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)
复制代码

上面的代码中使用了rawget和rawset以避免死循环。使用这两个函数,可以避免Lua使用__index和__newindex。

运算符

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

复制代码
-- 创建重载+号行为的表变量 lo_table = setmetatable({ 1, 2, 3 }, {
  __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 + 2 -- 打印得到的结果 print(lo_table[1]) print(lo_table[2]) print(lo_table[3])
复制代码

和__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(1, 2, 3, 4) print(result)
复制代码

 

__tostring

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

复制代码
lo_table = setmetatable({ 1, 2, 3 }, {
  __tostring = function(lo_table)
    sum = 0 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 0, y = y or 0 }, 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(12, 10)
b = Vector(20, 11)
c = a + b print(a) print(c)
复制代码

本文转载自:http://www.cnblogs.com/daxiaxiaohao/p/4651767.html

共有 人打赏支持
浩浩老师
粉丝 1
博文 80
码字总数 0
作品 0
海淀
程序员
【Lua高级教程】什么是Metatable举例说明

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

浩浩老师
2015/09/08
81
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
54
2
Python、Lua和Ruby三大语言脚本哪家强?

这三种语言中的哪一种更合适你的项目?很大程度取决于你想达到什么样的目标。作为一书的结尾,在这一节里,我会描述一下它们各自的优点和不足。 Python的优点和不足 Python的优点如下: 1. P...

柯西带你学编程
06/01
0
0
Tinywan/lua-nginx-redis

在线文档(Online documentation) 目录 Nginx 教程 (Nginx tutorial) Nginx编译安装 Nginx.conf详解和配置 Location 详解和配置 Nginx基础知识 Nginx高性能WEB服务器详解 Nginx高并发系统...

Tinywan
01/07
0
0
Cocos2d-x 脚本语言Lua介绍

https://blog.csdn.net/wwj_748/article/details/31837997 Cocos2d-x 脚本语言Lua介绍 本篇博客记录Lua学习,学习来自eoe论坛,Lua语言开发Cocos2d-x游戏入门视频教程,猛戳以下地址: http...

tropicofcancer9
04/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

DeepMind 开源图神经网络的代码

用于支持论文《Relational inductive biases, deep learning, and graph networks》。 github A graph network takes a graph as input and returns a graph as output. The input graph has......

shengjuntu
30分钟前
1
0
python2编码详解、一

以前使用python3没觉的什么,跟着公司使用python2后被编码问题折磨的痛不欲生,好好研究了一下编码问题,参考了很多博文,加入自己的理解,这里只是对编码的介绍,下一篇是python2中编码问题...

hc321
39分钟前
1
0
基于OpenSSL的一些常用加密签名算法

目前包括:MD5、SHA512、DES、RSA加解密、RSA+MD5签名验证算法,在openssl基础上再进行封装,使用简单,头文件需要包含openssl库,可以使用vcpkg自动管理,省去繁琐的配置工程的过程。 该RSA...

LoSingSang
47分钟前
1
0
spring Data JPA

什么是JPA? 全称Java Persistence API,可以通过注解或者XML描述【对象-关系表】之间的映射关系,并将实体对象持久化到数据库中。 为我们提供了: 1)ORM映射元数据:JPA支持XML和注解两种元...

狼王黄师傅
52分钟前
1
0
微信小程序 - 使用七牛云 API 截取第 n 秒图像为封面图

前面分享过七牛的上传操作,在这里说下使用七牛 api 对视频在页面的处理,比如你的视频上传之后获取七牛视频链接,这时候你怎么展示它呢? 在页面可以使用小程序提供的原生组件 video ,可以...

几个栗子
55分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部