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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值