文档章节

[Lua]Lua高级教程Metatables

浩浩老师
 浩浩老师
发布于 2015/10/20 14:15
字数 1041
阅读 30
收藏 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

没有更多内容

加载失败,请刷新页面

加载更多

Andrew Ng教你如何引领公司进入AI时代

摘要: 人工智能时代,企业转型遇到困难?看看Andrew Ng的建议吧! AI(人工智能)技术就像100年前的电力一样,正准备改变每个行业。从现在到2030年,它将创造约13万亿美元的GDP增长。虽然它...

阿里云官方博客
15分钟前
1
0
斗图咖(www.doutuka.com)上线纪念

网站名称:斗图咖 网站描述:是一款年轻人都在玩的斗图网站,来斗图咖一起斗图装逼交朋友吧。站长每天上传收集的最新最火斗图,供大家娱乐聊天发表情;后期也会开发表情自主设计,自己设计表...

focusone
36分钟前
4
0
Spring AOP 切面编程记录日志和接口执行时间

最近客户现在提出系统访问非常慢,需要优化提升访问速度,在排查了nginx、tomcat内存和服务器负载之后,判断是数据库查询速度慢,进一步排查发现是因为部分视图和表查询特别慢导致了整个系统...

编程SHA
47分钟前
8
0
15个Spring的核心注释示例

众所周知,Spring DI和Spring IOC是Spring Framework的核心概念。让我们从org.springframework.beans.factory.annotation和org.springframework.context.annotation包中探索一些Spring核心注......

java菜分享
53分钟前
2
0
[LintCode] Binary Tree Level Order Traversal(二叉树的层次遍历)

描述 给出一棵二叉树,返回其节点值的层次遍历(逐层从左往右访问) 样例 给一棵二叉树 {3,9,20,#,#,15,7} : 3 / \9 20 / \ 15 7 返回他的分层遍历结果: [ [3], [...

honeymose
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部