版权声明: https://blog.csdn.net/qq_28710983/article/details/82943918
重要:在表和元表的__index 和 __newindex 都没有需要操作的key时,赋值table操作会调用__newindex, 取值操作会调用__index
元表设置setmetatable
t1 = {};
t2 = {};
print("t1=",t1);
print("t2=",t2);
print(setmetatable(t1,t2)); ----t2是元表 t1是普通表 打印的是t1的表
print(getmetatable(t1)); --getmetatable(t1),得到的是t2的表的地址
-----------------------------------------------------------------------
-----------------------------------------------------------------------
output:
t1= table: 00719A08
t2= table: 00719A30
table: 00719A08
table: 00719A30
元方法:重载加号"+"
t1 = {1,2,3};
t2 = {4,5,6};
mt = {}
mt.__add = function(a,b)
local n = #a;
local res = {};
for i=1,n do
res[i] = a[i] + b[i];
end
return res;
end
setmetatable(t1,mt);
setmetatable(t2,mt);
t3 = t1 + t2; ----__add重载了+号,所有t1可以加t2
print(t3[1]);
---------------------------------------------------------------
output:
5
重载关系比较运算符"=="
a = {x=1,y=2,z=3};
b = {x=1,y=1,z=1};
mt = {}
mt.__eq = function(a,b)
if a[1] == b[1] and a[2] == b[2] and a[3] == b[3] then
return true;
else
return false;
end
end
setmetatable(a,mt);
setmetatable(b,mt);
if a == b then
print("a == b"); --设置了元方法eq就相等
else
print("a ~= b"); --如果不重载元方法eq就会不相等
end
----------------------------------------------------------------------
output:
a == b
__index 元方法
这是metatable最常用的键,当你通过key来访问table的时候,如果没有这个键值,那么lua就会寻找该table的metatable(假定有metatable)中的__index键,如果__index包含一个表,lua会在表格中查找相应的键
t = {};
mt = {};
setmetatable(t,mt); ----设置mt为t的元表
print(t.x); ----t.x没有这个键,然后就会去查找mt.__index 键,mt也没有这个键所以会返回nil
-----------------------------------
output:
nil
元表有__index键
t = {};
mt = {
__index = {
x = "123"
}
};
setmetatable(t,mt); ----设置mt为t的元表
print(t.x); ----t.x没有这个键,然后就会去查找mt.__index 键,x = "123"
---------------------------------------------------
output:
123
元表没有__index键,元表有x键
t = {};
mt = {
x = "123"
};
setmetatable(t,mt); ----设置mt为t的元表
print(t.x); ----t.x没有这个键,取值搜索只会取元表的__index键,所有mt有x,t.x也是输出nil
-----------------------------------
output:
nil
__index为函数
如果__index包含一个函数的话,且没有取值的键,lua就会调用哪个函数,table和键会作为参数传递给函数
t = {};
mt = {
__index = function ()
print("__index function")
end
};
setmetatable(t,mt);
print(t.x);
-------------------------------------------
output:
__index function
nil
如果有函数,但是也有jian,就不执行函数
t = {};
mt = {
__index = {function ()
print("__index function")
end,
x = "100"
}
};
setmetatable(t,mt);
print(t.x);
-------------------------------------------------------
output:
100
实际当__index只有函数时,会把table和取值key传入到__index的函数中
t = {};
print("t:",t);
mt = {
__index = function (t,k) ---
print(t,k)
if k == "x" then
t[k] = 777;
return 888;
else
return 999;
end
end
};
setmetatable(t,mt);
print(t.x); ----会把table和key传入到__index的function中去 ,output : 888,这里调用t.x没有值,然后会给t.x赋值777
print(t.x); ----output:777 , 这里t.x = 777
--------------------------------------------------------
output:
t: table: 00E19D00 -----这里是t的table
table: 00E19D00 x -----这里打印的是t的table和 t.x传递的x键名称
888
777
__newindex元方法
__newindex元方法用来对表进行更新(赋值),__index则用来对表进行访问(取值)
当你给表一个缺少的索引赋值,解释器就会查找__newindex元方法:如果存在则调用这个函数而不进行赋值操作
__newindex元方法如果是一张表,lua对这张表索引赋值操作,新的k v会出现在表中
t = { };
mt = { };
print("table t:",t); ---output: table t: table: 008E9C10
setmetatable(t,mt);
mt.__newindex = function (t,k,v) --- t.y会把 table:t,key: y,value:100 ,传递进去
print(t,k,v);
end
mt.__index = function (t,k) ---
if k == "x" then
t[k] = 777; ---table: 008E9C10 x 777 这里是赋值还会调用一次__newindex
return 888;
else
return 999;
end
end
t.x = 100; ------output: table: 008E9C10 x 100 ,t没有x键,执行了__newindex的函数但是不进行赋值
print(t.x); ------output: 888 t.x是取值不进行赋值操作,
--------------------------------------
output:
table t: table: 008E9C10
table: 008E9C10 x 100
table: 008E9C10 x 777
888
表象函数一样调用(原理还是重载了方法__call)
pow = {};
setmetatable(pow,{__call = function(t,x)
return x * x ;
end})
print(pow(10));
---------------------------------
output:
100
重载__tostring方法
pow = setmetatable({10,20,30},{__tostring = function(t)
sum = 0;
for k,v in pairs(t) do
sum = sum + v;
end
return "sum = " .. sum;
end})
print(pow);
---------------------------------------------------
output:
sum = 60
rawset 和 rawget是直接操作表,而不去访问元表
Window = {}
Window.prototype = {x = 0 ,y = 0 ,width = 100 ,height = 100,}
Window.mt = {}
function Window.new(o)
setmetatable(o ,Window.mt)
return o
end
Window.mt.__index = function (t ,key)
return 1000
end
Window.mt.__newindex = function (table ,key ,value)
if key == "wangbin" then
rawset(table ,"wangbin" ,"yes,i am") --(1)
--table.wangbin = "yes,i am" --(2)反例
end
end
w = Window.new({x = 10 ,y = 20} )
print(rawget(w ,w.wangbin)) ------取的是w表里面的wangbin键,为nil
print(w.wangbin) ------没有使用raw取的就是元表里面的__index所以为1000
w.wangbin = "nVal" ------w没有wangbin键,就执行元表里面的__newindex的方法
print(w.wangbin) ------输出yes,i am
rawset(w,"wangbin","nVal") ----使用rawset,就设置w表里面的wangbin键位nVal
print(w.wangbin) ----输出nVal
----------------------------------------------------
output:
nil
1000
yes,i am
nVal