• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell
您的位置:首页 > 脚本语言 >Lua > Lua中的元表与元方法学习总结

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

作者: 字体:[增加 减小] 来源:互联网

通过本文主要向大家介绍了Lua中的迭代器和泛型for学习总结等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

前言

元表对应的英文是metatable,元方法是metamethod。我们都知道,在C++中,两个类是无法直接相加的,但是,如果你重载了“+”符号,就可以进行类的加法运算。在Lua中也有这个道理,两个table类型的变量,你是无法直接进行“+”操作的,如果你定义了一个指定的函数,就可以进行了。那这篇博文就是主要讲的如何定义这个指定的函数,这个指定的函数是什么?希望对学习Lua的朋友有帮助。

Lua是怎么做的?

通常,Lua中的每个值都有一套预定义的操作集合,比如数字是可以相加的,字符串是可以连接的,但是对于两个table类型,则不能直接进行“+”操作。这需要我们进行一些操作。在Lua中有一个元表,也就是上面说的metatable,我们可以通过元表来修改一个值得行为,使其在面对一个非预定义的操作时执行一个指定的操作。比如,现在有两个table类型的变量a和b,我们可以通过metatable定义如何计算表达式a+b,具体的在Lua中是按照以下步骤进行的:

先判断a和b两者之一是否有元表;
检查该元表中是否有一个叫__add的字段;
如果找到了该字段,就调用该字段对应的值,这个值对应的是一个metamethod;(Lua中方法是可以放在一个字段中的,还记得???忘了点这里)
调用__add对应的metamethod计算a和b的值。
上述四个步骤就是计算table类型变量a+b的过程。在Lua中,每个值都有一个元表,table和userdata类型的每个变量都可以有各自独立的元表,而其他类型的值则共享其类型所属的单一元表。

告别metatable小白

现在就说说最基本的metatable内容。Lua在创建新的table时不会创建元表,比如以下代码就可以演示:
local t = {1, 2}
print(getmetatable(t))     -- nil
</div>
我们是使用getmetatable来获取一个table或userdata类型变量的元表,当创建新的table变量时,使用getmetatable去获得元表,将返回nil;同理,我们也可以使用setmetatable去设置一个table或userdata类型变量的元表,例如以下代码:
local t = {}
print(getmetatable(t))     -->nil
 
local t1 = {}
setmetatable(t, t1)
assert(getmetatable(t) == t1)
</div>
任何table都可以作为任何值得元表,而一组相关的table有可以共享一个通用的元表,此元表描述了它们共同的行为。一个table甚至可以作为它自己的元表,用于描述其特有的行为。总之,任何搭配形式都是合法的。

在Lua代码中,只能设置table的元表。若要设置其它类型的值得元表,则必须通过C代码来完成。还存在一个特例,对于字符串,标准的字符串程序库为所有的字符串都设置了一个元表,而其它类型在默认情况下都没有元表。查看两句代码的打印值,就可以看出来:

print(getmetatable("Hello World"))
print(getmetatable(10))
</div>

在table中,我可以重新定义的元方法有以下几个:

__add(a, b) --加法
__sub(a, b) --减法
__mul(a, b) --乘法
__div(a, b) --除法
__mod(a, b) --取模
__pow(a, b) --乘幂
__unm(a) --相反数
__concat(a, b) --连接
__len(a) --长度
__eq(a, b) --相等
__lt(a, b) --小于
__le(a, b) --小于等于
__index(a, b) --索引查询
__newindex(a, b, c) --索引更新(PS:不懂的话,后面会有讲)
__call(a, ...) --执行方法调用
__tostring(a) --字符串输出
__metatable --保护元表
</div>

接下来就介绍介绍如果去重新定义这些方法。

算术类的元方法

现在我使用完整的实例代码来详细的说明算术类元方法的使用。我准备定义一些对集合的操作方法,所有的方法都放入Set这个table中,至于为什么table中可以存放函数,可以参考《Lua中的函数》这篇文章。下面的代码是我模拟的一个集合的操作:

Set = {}
local mt = {} -- 集合的元表
 
-- 根据参数列表中的值创建一个新的集合
function Set.new(l)
    local set = {}
     setmetatable(set, mt)
    for _, v in pairs(l) do set[v] = true end
     return set
end
 
-- 并集操作
function Set.union(a, b)
    local retSet = Set.new{} -- 此处相当于Set.new({})
    for v in pairs(a) do retSet[v] = true end
    for v in pairs(b) do retSet[v] = true end
    return retSet
end
 
-- 交集操作
function Set.intersection(a, b)
    local retSet = Set.new{}
    for v in pairs(a) do retSet[v] = b[v] end
    return retSet
end
 
-- 打印集合的操作
function Set.toString(set)
     local tb = {}
     for e in pairs(set) do
          tb[#tb + 1] = e
     end
     return "{" .. table.concat(tb, ", ") .. "}"
end
 
function Set.print(s)
     print(Set.toString(s))
end
</div>

现在,我定义“+”来计算两个集合的并集,那么就需要让所有用于表示集合的table共享一个元表,并且在该元表中定义如何执行一个加法操作。首先创建一个常规的table,准备用作集合的元表,然后修改Set.new函数,在每次创建集合的时候,都为新的集合设置一个元表。代码如下:

Set = {}
local mt = {} -- 集合的元表
 
-- 根据参数列表中的值创建一个新的集合
function Set.new(l)
    local set = {}
     setmetatable(set, mt)
    for _, v in pairs(l) do set[v] = true end
     return set
end
</div>

在此之后,所有由Set.new创建的集合都具有一个相同的元表,例如:

local set1 = Set.new({10, 20, 30})
local set2 = Set.new({1, 2})
print(getmetatable(set1))
print(getmetatable(set2))
assert(getmetatable(set1) == getmetatable(set2))
</div>

最后,我们需要把元方法加入元表中,代码如下:

mt.__add = Set.union
</div>
这以后,只要我们使用“+”符号求两个集合的并集,它就会自动的调用Set.union函数,并将两个操作数作为参数传入。比如以下代码:

您可能想查找下面的文章:

相关文章

  • Lua中的metatable介绍
  • Lua中获取table长度的方法
  • Lua中遍历文件操作代码实例
  • 详解Lua中的数组概念知识
  • Lua教程(八):数据持久化
  • Lua基础教程之表(Table)学习笔记
  • Lua读取和写入文件处理例子
  • 使用Lua来扩展C++程序的方法
  • Lua常用时间函数使用实例
  • Lua中的类编程代码实例

文章分类

  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell

最近更新的内容

    • Lua中释放table占用内存的方法
    • Lua 学习笔记之C API 遍历 Table实现代码
    • Lua教程(十六):系统库(os库)
    • 把Lua函数传递到C/C++中实例
    • Lua中for循环语句的使用教程
    • LUA中的闭包(closure)浅析
    • Lua中的闭包小结
    • linux系统安装Nginx Lua环境
    • Lua中函数的几个特别之处探究
    • Lua中的协同程序探究

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有