Lua进阶

1.Meatatable(元表)

metatable是table预定义的一系列操作。比如将两个table相加,那么Lua会先去检查两个table中是否有metatable,然后在检查metatable是否有__add方法,如果有就按照__add方法中的操作来执行,否则会报错。

Lua中的新建的table的时候是不会创建metatable的,需要使用setmetatable()来设置元表。

注意:setmetatable()可以是任意的table,包括要赋值的table本身。

Lua中检查是否有元表使用getmetatable()

print(getmetatable(nil)); // 输出为:nil,表示nil没有元表

实现table+的运算

Set = {};

function Set.new(t)
    local set = {};
    for i, v in ipairs(t) do
        set[i] = v;
    end
    return set;
end

function  Set.union(a, b)
    local res = {};
    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.tostring(set)
    local str = "{";
    local sep = "";
    for k, v in pairs(set) do
        str = str..sep..k;
        sep = ",";
    end
    return s.."}";
end

// 输出函数
function Set.print(set)
    print(Set.tostring(set));
end

// 设置元表
Set.mt = {};
setetatable(Set, Set.mt);

// 设置Set的元表`__add`元方法指向的`Set.union`函数
Set.mt.__add = Set.union;

// 测试Set
s1 = Set.new({10,20,30,50});
s2 = Set.new(30,1);
s3 = s1 + s2;
Set.print(s3); // 输出为:1,20,30,50,20

2.元方法

table还有其他的元方法(元表的方法),罗列如下:

__index    // 默认值
function(table,key)

__newindex // 赋值
function(table,key,value)

__tostring  // 被print()调用
__metatable // 设置后可隐藏mt

__eq // 等于
__lt // 小于
__le // 小于等于

__add // 加
__sub // 减
__mul // 乘
__div // 除
__unm // 负
__pow // 幂
__concat // 连接

重要的元方法介绍
1.__index元方法
Lua中访问table元素是先通过__index元方法先查找是否有这个函数,如果没有就返回nil
__index的值可以是一个table或者函数,如果是table则会以该table作为索引进行查询,若是函数,则将table和缺少的域作为参数调用这个函数。

Window = {};
Window.mt = {};
Window.prototype = {x = 0, y = 0, width = 100, height = 100};
Window.mt.__index = function(table,key)
    return Window.prototype[key];
end

function Window.new(t)
    setmetatable(t,Window.mt);
    return t;
end

// 测试
w = Window.new({x = 10,y = 20});
print(w.height);  // 输出为:100

2.__newindex元方法
__newindex用于table的更新,__index用于table的查询操作,当对table中不存在的索引赋值时,就会调用__newindex元方法

Window = {};
Window.mt = {};
Window.mt.__newindex = function(table,key,value)
    print("update of element"..tostring(key)..tostring(value));
    rawset(table,key,value);
end

function Window.new(t)
    setmetatable(t,Window.mt);
    return t;
end

// 测试
window = Window.new({x = 10,y = 20});
window.a = 10;

总结:
__indexget表中未定义元素时触发,对应有rawset(table,key)来避免调用__index;
__newindexset表中未定义元素时触发,对应有的rawset(table,key)来避免调用__newindex

### Lua 进阶教程:高级语法示例 以下是几个常见的 Lua 高级语法示例及其应用场景: #### 1. 使用 `require` 加载模块 在 Lua 中,可以通过 `require()` 函数加载外部模块。此函数无需指定 `.lua` 后缀名,并支持相对路径或绝对路径的模块导入。 ```lua -- 假设有一个名为 mymodule 的文件在同一目录下 local myModule = require("mymodule") -- 不需要写 .lua 后缀 myModule.someFunction() ``` 如果模块位于不同的路径,则需提供完整路径或者修改包路径配置[^1]。 --- #### 2. 元表 (Metatables) 和元方法 (Metamethods) Lua 提供了一种强大的机制——元表,用于自定义数据类型的运算行为。通过设置元表中的特定键值对(即元方法),可以改变对象的行为方式。 ```lua -- 定义两个向量 local vectorA = {x=1, y=2} local vectorB = {x=3, y=4} -- 设置元表并实现加法操作 setmetatable(vectorA, { __add = function(a, b) return {x=a.x+b.x, y=a.y+b.y} end }) -- 执行加法 local resultVector = vectorA + vectorB print(resultVector.x, resultVector.y) -- 输出: 4 6 ``` 上述代码展示了如何利用元表重载加法运算符[^5]。 --- #### 3. 协程 (Coroutines) 协程允许程序暂停当前执行流程并在稍后恢复运行状态。这种功能非常适合异步任务管理以及复杂的控制流设计。 ```lua -- 创建一个简单的协程 local co = coroutine.create(function () print("Coroutine started") coroutine.yield(10) -- 暂停并将值返回给调用者 print("Resumed after yield") end) -- 启动协程 coroutine.resume(co) -- 输出 Coroutine started local status, value = coroutine.resume(co) -- 继续执行至下一个 yield 或结束 if not status then error(value) end print(value) -- 输出 Resumed after yield ``` 这段代码演示了创建、启动和恢复协程的过程。 --- #### 4. Redis 中的 Lua 脚本执行 当 Lua 结合数据库系统如 Redis 使用时,能够显著提高性能与灵活性。Redis 支持直接嵌入 Lua 脚本来批量处理请求逻辑。 ```lua -- 示例:原子计数器增量更新 redis.call('INCR', KEYS[1]) return redis.call('GET', KEYS[1]) -- 在客户端中调用 eval 命令传参 EVAL "..." 1 key_name increment_value ``` 这里提到的是 Redis 如何借助 C 层面接口解析并运行 Lua 脚本[^3]。 --- #### 5. 调试工具集成 对于更深入的学习需求来说,掌握调试技巧尤为重要。例如基于 Visual Studio Code 平台配合插件可轻松完成断点跟踪等功能;另外还有专门针对 Lua 开发者的第三方库比如 **LuaInterface-Debugger** 可进一步增强体验效果[^4]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值