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

Lua中的metatable详解

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

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

Lua 中 metatable 是一个普通的 table,但其主要有以下几个功能:

1.定义算术操作符和关系操作符的行为
2.为 Lua 函数库提供支持
3.控制对 table 的访问

Metatables 定义操作符行为

Metatable 能够被用于定义算术操作符和关系操作符的行为。例如:Lua 尝试对两个 table 进行加操作时,它会按顺序检查这两个 table 中是否有一个存在 metatable 并且这个 metatable 是否存在 __add 域,如果 Lua 检查到了这个 __add 域,那么会调用它,这个域被叫做 metamethod。

Lua 中每个 value 都可以有一个 metatable(在 Lua 5.0 只有 table 和 userdata 能够存在 metatable)。每个 table 和 userdata value 都有一个属于自己的 metatable,而其他每种类型的所有 value 共享一个属于本类型的 metatable。在 Lua 代码中,通过调用 setmetatable 来设置且只能设置 table 的 metatable,在 C/C++ 中调用 Lua C API 则可以设置所有 value 的 metatable。默认的情况下,string 类型有自己的 metatable,而其他类型则没有:

print(getmetatable('hi')) --> table: 003C86B8
print(getmetatable(10))  --> nil
</div>

Metamethod 的参数为操作数(operands),例如:

local mt = {}
function mt.__add(a, b)
    return 'table + ' .. b
end
local t = {}
setmetatable(t, mt)
print(t + 1)
</div>

每个算术操作符有对应的 metamethod:

+ __add
* __mul
- __sub
/ __div
- __unm (for negation)
% __mod
^ __pow

对于连接操作符有对应的 metamethod:__concat

同样,对于关系操作符也都有对应的 metamethod:

== __eq
< __lt
<= __le

其他的关系操作符都是用上面三种表示:
a ~= b 表示为 not (a == b)
a > b 表示为 b < a
a >= b 表示为 b <= a

和算术运算符不同的是,关系运算符用于比较拥有不同的 metamethod(而非 metatable)的两个 value 时会产生错误,例外是比较运算符,拥有不同的 metamethod 的两个 value 比较的结果是 false。

不过要注意的是,在整数类型的比较中 a <= b 可以被转换为 not (b < a),但是如果某类型的所有元素并未适当排序,此条件则不一定成立。例如:浮点数中 NaN(Not a Number)表示一个未定义的值,NaN <= x 总是为 false 并且 x < NaN 也总为 false。

为 Lua 函数库提供支持

Lua 库可以定义和使用的 metamethod 来完成一些特定的操作,一个典型的例子是 Lua Base 库中 tostring 函数(print 函数会调用此函数进行输出)会检查并调用 __tostring metamethod:

local mt = {}
mt.__tostring = function(t)
    return '{' .. table.concat(t, ', ') .. '}'
end
 
local t = {1, 2, 3}
print(t)
setmetatable(t, mt)
print(t)
</div>

另外一个例子是 setmetatable 和 getmetatable 函数,它们定义和使用了 __metatable 域。如果你希望设定的 value 的 metatable 不被修改,那么可以在 value 的 metatable 中设置 __metatable 域,getmetatable 将返回此域,而 setmetatable 则会产生一个错误:

mt.__metatable = "not your business"
local t = {}
setmetatable(t, mt)
print(getmetatable(t)) --> not your business
setmetatable(t, {})
    stdin:1: cannot change protected metatable
</div>

看一个完整的例子:

Set = {}
 
local mt = {}
 
function Set.new(l)
    local set = {}
    -- 为 Set 设置 metatable
    setmetatable(set, mt)
    for _, v in ipairs(l) do set[v] = true end
    return set
end
 
function Set.union(a, b)
    -- 检查 a b 是否都是 Set
    if getmetatable(a) ~= mt or getmetatable(b) ~= mt then
        -- error 的第二个参数为 level
        -- level 指定了如何获取错误的位置
        -- level 值为 1 表示错误的位置为 error 函数被调用的位置
        -- level 值为 2 表示错误的位置为调用 error 的函数被调用的地方
        error("attempt to 'add' a set with a not-set value", 2)
    end
    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
 
mt.__add = Set.union
mt.__mul = Set.intersection
 
mt.__tostring = function(s)
    local l = {}
    for e in pairs(s) do
        l[#l + 1] = e
    end
    return '{' .. table.concat(l, ', ') .. '}'
end
 
mt.__le = function(a, b)
    for k in pairs(a) do
        if not b[k] then return false end
    end
    return true
end
 
mt.__lt = function(a, b)
    return a <= b and not (b <= a)
end
 
mt.__eq = function(a, b)
    return a <= b and b <= a
end
 
local s1 = Set.new({1, 2, 3})
local s2 = Set.new({4, 5, 6})
print(s1 + s2)
print(s1 ~= s2)
</div>

控制 table 的访问

__index metamethod

在我们访问 table 的不存在的域时,Lua 会尝试调用 __index metamethod。__index metamethod 接受两个参数 table 和 key:
local mt = {}

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

  • Lua编程示例(二):面向对象、metatable对表进行扩展
  • Lua中的metatable介绍
  • Lua中的metatable详解

相关文章

  • Lua编程中的一些基本语法整理
  • Lua中全局变量与非全局环境介绍
  • 浅谈Lua语句
  • Lua table中安全移除元素的方法
  • Lua loadstring函数用法实例
  • Lua UnPack函数用法实例
  • Lua中的递归函数写法实例
  • lua文件操作详解
  • Lua中string.lower()使用指南
  • Lua所有内置函数罗列

文章分类

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

最近更新的内容

    • C语言中通过LUA API访问LUA脚本变量的简单例子
    • 把Lua函数传递到C/C++中实例
    • Lua 学习笔记之C API 遍历 Table实现代码
    • Lua中的协同程序详解
    • Lua中调用C++函数示例
    • Lua中编译执行代码相关的函数详解
    • C语言中调用Lua函数实例
    • Lua中变相实现continue跳出循环
    • openresty中使用lua-nginx创建socket实例
    • Lua的内存管理浅析

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

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