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

Lua教程(九):元表与元方法详解

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

junjie 通过本文主要向大家介绍了lua源码详解与应用,lua 详解,lua教程,cocos2dx lua教程,cocos2d lua教程等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

Lua中提供的元表是用于帮助Lua数据变量完成某些非预定义功能的个性化行为,如两个table的相加。假设a和b都是table,通过元表可以定义如何计算表达式a+b。当Lua试图将两个table相加时,它会先检查两者之一是否有元表,然后检查该元表中是否存在__add字段,如果有,就调用该字段对应的值。这个值就是所谓的“元方法”,这个函数用于计算table的和。

 Lua中每个值都有一个元表。table和userdata可以有各自独立的元表,而其它数据类型的值则共享其类型所属的单一元表。缺省情况下,table在创建时没有元表,如:
      t = {}
    print(getmetatable(t))  --输出为nil
</div>
    这里我们可以使用setmetatable函数来设置或修改任何table的元表。
    t1 = {}
    setmetatable(t,t1)
    assert(getmetatable(t) == t1)
</div>
    任何table都可以作为任何值的元表,而一组相关的table也可以共享一个通用的元表,此元表将描述了它们共同的行为。一个table甚至可以作为它自己的元表,用于描述其特有的行为。在Lua代码中,只能设置table的元表,若要设置其它类型值的元表,则必须通过C代码来完成。

    1. 算术类的元方法:

    在下面的示例代码中,将用table来表示集合,并且有一些函数用来计算集合的并集和交集等。
   Set = {}
local metatable = {} --元表

--根据参数列表中的值创建一个新的集合
function Set.new(l)
    local set = {}
    --将所有由该方法创建的集合的元表都指定到metatable
    setmetatable(set,metatable)
    for _, v in ipairs(l) do
        set[v] = true
    end
    return set
end

--取两个集合并集的函数
function Set.union(a,b)
    local res = Set.new{}
    for k in pairs(a) do
        res[k] = true
    end
    for k in pairs(b) do
        res[k] = true
    end
    return res
end

--取两个集合交集的函数
function Set.intersection(a,b)
    local res = Set.new{}
    for k in pairs(a) do
        res[k] = b[k]
    end
    return res
end

function Set.tostring(set)
    local l = {}
    for e in pairs(set) do
        l[#l + 1] = e
    end
    return "{" .. table.concat(l,", ") .. "}";
end

function Set.print(s)
    print(Set.tostring(s))
end

--最后将元方法加入到元表中,这样当两个由Set.new方法创建出来的集合进行
--加运算时,将被重定向到Set.union方法,乘法运算将被重定向到Set.intersection
metatable.__add = Set.union
metatable.__mul = Set.intersection

--下面为测试代码
s1 = Set.new{10,20,30,50}
s2 = Set.new{30,1}
s3 = s1 + s2
Set.print(s3)
Set.print(s3 * s1)

--输出结果为:
--{1, 30, 10, 50, 20}
--{30, 10, 50, 20}
 </div>

 在元表中,每种算术操作符都有对应的字段名,除了上述的__add(加法)和__mul(乘法)外,还有__sub(减法)、__div(除法)、__unm(相反数)、__mod(取模)和__pow(乘幂)。此外,还可以定义__concat字段,用于描述连接操作符的行为。

对于上面的示例代码,我们在算术运算符的两侧均使用了table类型的操作数。那么如果为s1 = s1 + 8,Lua是否还能正常工作呢?答案是肯定的,因为Lua定位元表的步骤为,如果第一个值有元表,且存在__add字段,那么Lua将以这个字段为元方法,否则会再去查看第二个值否是有元表且包含__add字段,如果有则以此字段为元方法。最后,如果两个值均不存在元方法,Lua就引发一个错误。然而对于上例中的Set.union函数,如果执行s1 = s1 + 8将会引发一个错误,因为8不是table对象,不能基于它执行pairs方法调用。为了得到更准确的错误信息,我们需要给Set.union函数做如下的修改,如:
function Set.union(a,b)
    if getmetatable(a) ~= metatable or getmetatable(b) ~= metatable then
        error("attempt to 'add' a set with a non-set value")
    end
    --后面的代码与上例相同。
    ... ...
end
</div>

2. 关系类的元方法:

    元表还可以指定关系操作符的含义,元方法分别为__eq(等于)、__lt(小于)和__le(小于等于),至于另外3个关系操作符,Lua没有提供相关的元方法,可以通过前面3个关系运算符的取反获得。见如下示例:
Set = {}
local metatable = {}

function Set.new(l)
    local set = {}
    setmetatable(set,metatable)
    for _, v in ipairs(l) do
        set[v] = true
    end
    return set
end

metatable.__le = function(a,b)
    for k in pairs(a) do
        if not b[k] then return false end
    end
    return true
end
metatable.__lt = function(a,b) return a <= b and not (b <= a) end
metatable.__eq = function(a,b) return a <= b and b <= a end

--下面是测试代码:
s1 = Set.new{2,4}
s2 = Set.new{4,10,2}
print(s1 <= s2) --true
print(s1 < s2)  --true
print(s1 >= s1) --true
print(s1 > s1)  --false
</div>

 与算术类的元方法不同,关系类的元方法不能应用于混合的类型。

    3. 库定义的元方法:

    除了上述基于操作符的元方法外,Lua还提供了一些针对框架的元方法,如print函数总是调用tostring来格式化其输出。如果当前对象存在__tostring元方法时,tostring将用该元方法的返回值作为自己的返回值,如:
Set = {}
local metatable = {}

function Set.new(l)
    local set = {}
    setmetatable(set,metatable)
    for _, v in ipairs(l) do
        set[v] = true
    end
    return set
end

function Set.tostring(set)
    local l = {}
    for e in pa

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

  • lua文件操作详解
  • 举例详解Lua中的协同程序编程
  • 详解Lua中的元表概念
  • 详解Lua中的数组概念知识
  • 详解Lua中if ... else语句的使用方法
  • 详解Lua中的if语句的使用方法
  • 详解Lua中的while循环语句的使用
  • 详解Lua中的数据类型
  • 详解Lua中的变量相关知识点
  • lua中赋值类型代码详解

相关文章

  • C++遍历Lua table的方法实例
  • C调用lua函数需要考虑的问题
  • lua中使用packagepath解决多个项目的路径冲突问题
  • Lua中使用元表(metatable)执行算术类元方法实例
  • Lua中关系运算符的使用教程
  • Lua中的元方法__newindex详解
  • Linux下编写Lua扩展so文件和调用方法实例
  • Lua中的模块与module函数详解
  • Lua中实现StringBuffer功能
  • Lua脚本自动生成APK包

文章分类

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

最近更新的内容

    • Lua中的string库和强大的模式匹配学习笔记
    • 把Lua函数传递到C/C++中实例
    • Lua获取utf8字符串长度和字符串截取并用...代替
    • Lua中的函数代码实例
    • Lua教程(十二):面向对象编程
    • Lua 中 pairs 和 ipairs 的区别
    • Lua中调用C++函数实例
    • Lua中的弱引用介绍
    • Lua中使用二维数组实例
    • Lua中类的实现

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

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