文档章节

[Lua]Lua高级教程Metatables

浩浩老师
 浩浩老师
发布于 2015/10/20 14:15
字数 1041
阅读 27
收藏 3
点赞 0
评论 0

什么是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 ⋅ 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

Python、Lua和Ruby三大语言脚本哪家强?

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

柯西带你学编程 ⋅ 06/01 ⋅ 0

Tinywan/lua-nginx-redis

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

Tinywan ⋅ 01/07 ⋅ 0

Lua学习总结

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

临峰不畏 ⋅ 2013/10/08 ⋅ 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

使用Nginx+Lua+Redis进行Web开发

Openresty自带了Redis的接口。其实也就是一个lua脚本,该脚本负责了解redis,操作redis。 没有安装Openresty的同学,参考上一篇,安装Openresty。 没有安装Redis的同学,自己找个教程安装下,...

醉人的笑容你有没有 ⋅ 2016/04/17 ⋅ 0

Lua 环境搭建

Lua 环境搭建 --Windows 1. 登陆官网下载源码 -> www.lua.org -> get started -> installing 选择系统类型(这里是Windows的,所以下载 luaDist) 2. 下载 Binaries-LuaDist-batteries-0.9.8......

GREKI ⋅ 2014/08/22 ⋅ 0

(转)LUA与python根本就不具有可比性

网上经常看到别人拿lua与python来进行对比,但是,本人认为,lua与python根本就不具有可比性.原因如下: 1、两者的定位不同。python的定位在于自身的独立开发,即是说python定位于自己能解决所有...

Yisen ⋅ 2011/06/27 ⋅ 3

使用Nginx+Lua进行Web开发

Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。Lua由标准C编写而成,几乎在...

醉人的笑容你有没有 ⋅ 2016/04/17 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

使用 vue-cli 搭建项目

vue-cli 是一个官方发布 vue.js 项目脚手架,使用 vue-cli 可以快速创建 vue 项目,GitHub地址是:https://github.com/vuejs/vue-cli 一、 安装 node.js 首先需要安装node环境,可以直接到中...

初学者的优化 ⋅ 24分钟前 ⋅ 0

设计模式 之 享元模式

设计模式 之 享元模式 定义 使用共享技术来有效地支持大量细粒度对象的复用 关键点:防止类多次创建,造成内存溢出; 使用享元模式来将内部状态与外部状态进行分离,在循环创建对象的环境下,...

GMarshal ⋅ 39分钟前 ⋅ 0

SpringBoot集成Druid的最简单的小示例

参考网页 https://blog.csdn.net/king_is_everyone/article/details/53098350 建立maven工程 Pom文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM......

karma123 ⋅ 今天 ⋅ 0

Java虚拟机基本结构的简单记忆

Java堆:一般是放置实例化的对象的地方,堆分新生代和老年代空间,不断未被回收的对象越老,被放入老年代空间。分配最大堆空间:-Xmx 分配初始堆空间:-Xms,分配新生代空间:-Xmn,新生代的大小一...

算法之名 ⋅ 今天 ⋅ 0

OSChina 周日乱弹 —— 这么好的姑娘都不要了啊

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @TigaPile :分享曾惜的单曲《讲真的》 《讲真的》- 曾惜 手机党少年们想听歌,请使劲儿戳(这里) @首席搬砖工程师 :怎样约女孩子出来吃饭,...

小小编辑 ⋅ 今天 ⋅ 8

Jenkins实践3 之脚本

#!/bin/sh# export PROJ_PATH=项目路径# export TOMCAT_PATH=tomcat路径killTomcat(){pid=`ps -ef | grep tomcat | grep java|awk '{print $2}'`echo "tom...

晨猫 ⋅ 今天 ⋅ 0

Spring Bean的生命周期

前言 Spring Bean 的生命周期在整个 Spring 中占有很重要的位置,掌握这些可以加深对 Spring 的理解。 首先看下生命周期图: 再谈生命周期之前有一点需要先明确: Spring 只帮我们管理单例模...

素雷 ⋅ 今天 ⋅ 0

zblog2.3版本的asp系统是否可以超越卢松松博客的流量[图]

最近访问zblog官网,发现zlbog-asp2.3版本已经进入测试阶段了,虽然正式版还没有发布,想必也不久了。那么作为aps纵横江湖十多年的今天,blog2.2版本应该已经成熟了,为什么还要发布这个2.3...

原创小博客 ⋅ 今天 ⋅ 0

聊聊spring cloud的HystrixCircuitBreakerConfiguration

序 本文主要研究一下spring cloud的HystrixCircuitBreakerConfiguration HystrixCircuitBreakerConfiguration spring-cloud-netflix-core-2.0.0.RELEASE-sources.jar!/org/springframework/......

go4it ⋅ 今天 ⋅ 0

二分查找

二分查找,也称折半查找、二分搜索,是一种在有序数组中查找某一特定元素的搜索算法。搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;如果某一特定元素大于...

人觉非常君 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部