Lua中元表和元方法理解

元表

在 Lua table 中我们可以访问对应的key来得到value值,但是却无法对两个 table 进行操作。
因此 Lua 提供了元表(Metatable),它用于定义原始值在特定操作下的行为。如果你想改变一个值在特定操作下的行为,你可以在它的元表中设置对应域。例如,当你对非数字值做加操作时,Lua 会检查该值的元表中的 “__add” 域下的函数。如果能找到,Lua 则调用这个函数来完成加这个操作。

元表中的键对应着不同的 事件 名;键关联的那些值被称为 元方法。在下面例子中引用的事件为 “__add” ,完成加操作的那个函数就是元方法。

Vector2 ={
    x=0;
    y=0;
    mt={};

    New = function()
        local vec = {}
        --设置元表
        setmetatable(vec,Vector2.mt)
        vec.x = Vector2.x
        vec.y = Vector2.y
        vec.mt = Vector2.mt
        return vec
    end
}

Vector2.mt.__add = function(v1,v2)
        local vec = Vector2.New()
        vec.x = v1.x+v2.x
        vec.y = v1.y+v2.y
    return vec
end

---测试
----------------------------------------
v1 = Vector2.New()
v1.x = 1;
v1.y = 1;
v2 = Vector2.New()
v2.x = 10;
v2.y = 10;

v3 = v1 + v2
print(v3.x,v3.y)
----------------------------------------

有两个很重要的函数来处理元表:

setmetatable(table,metatable): 对指定 table 设置元表(metatable),如果元表(metatable)中存在 __metatable 键值,setmetatable 会失败。
getmetatable(table): 返回对象的元表(metatable)。

__index元方法

当我们对表的数据进行访问时会起作用
先上例子:

Window = {
    mt={},
    prototype = {x=0,y=0,width = 100,height=100},
    new = function(arg)
        setmetatable(arg,Window.mt)
        return arg
    end
}
​
Window.mt.__index = function(table,key)
    return Window.prototype[key]
end
​
b = {x=10,y=20}
w = Window.new(b)
print(w.width)

总结在Lua中查找一个表元素的规律

1.在表中查找一个表元素,如果找到,返回该元素,找不到则继续
2.判断该表是否有元表,如果没有元表,返回nil,有元表则继续
3.判断元表有没有__index方法,如果__index方法为nil,则返回nil;如果__index方法是一个表,则重复1、2、3;如果__index方法是一个函数,则返回该函数的返回值。

在上例中,在table w中找width,可得w表中没有width,w表中有元表mt,mt元表中有__index方法,__index方法是一个函数,返回prototype[width]。

__index可以是一个table

Window.mt.__index = Window.prototype   

因此调用表中一个不存在的值,可以在__index中做默认返回值

__newindex元方法

当我们对表的数据进行增加时,会起作用(和__index一样,都是表中的索引不存在)

1、__newindex是一个方法

myt = {"Lua","c#","c++","java"}
mymet = {
    __newindex = function(tab,key,value)
        print("修改的key为"..key,"把key改为"..value);
        -- tab[key] = value  这里不能这么做  tab[key]又赋值了一个不存在的索引 又会调用该方法 死循环
        rawset(tab,key,value)
    end
}
setmetatable(myt,mymet)
myt[5]="unity"
print(myt[5])

2、__newindex是一个表

myt = {"Lua","c#","c++","java"}
newtable = {}
mymet = {
    __newindex =newtable
}
setmetatable(myt,mymet)
myt[5]="unity"
print(myt[5])  --输出nil
print(newtable[5]) --输出unity

你可能感兴趣的:(Lua)