元表
在 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