设置元表
(似乎只能用 // 来注释?)
local mymetatable = {} //元表
local mytable = {} //表
//将mymetatable设置为mytable的元表
mytable = setmetatable(mytable,mymetatable)
元表是用来存放一些元方法,当对表执行某些指定操作时就会执行相应的元方法。
注意元方法的"__“是两个”_"
__index元方法
查询表时
local mytable1 = setmetatable({key1 = 1},{__index = {key2 = 2}})
print(mytable1.key1,mytable1.key2)
//这两种写法的结果相同-----------------------------------
local mytable2 = setmetatable({key1 = 11},{__index = function(mytable,key)
if key == "key2" then
return 22
else
return nil
end
end
})
print(mytable2.key1,mytable2.key2)
解析:
1.为mytable设置元表,
2.查询mytable中key1和key2键对应的值,
3.在mytable表中查询到key1键,返回对应的值,
4.在mytable中未找到key2键,查看mytable是否有元表,
5.有元表,在元表中是否有__index元方法,
6.(1)有__index元方法,元方法为表,则重复查询操作,
(2)有__index元方法,元方法为函数,将查询的表和key值作为形参传入函数,返回函数返回值,
7.输出结果
运行结果:
1 2
11 22
__newindex元方法
表更新时
local newtable = {key2 = 2,key3 = 3}
local mytable3 = setmetatable({key1 = 1},{__newindex = newtable})
mytable3.key1 = 11
mytable3.key2 = 22
mytable3.key4 = 44
print(mytable3.key1,mytable3.key2,mytable3.key3,mytable3.key4)
print(newtable.key1,newtable.key2,newtable.key3,newtable.key4)
解析:
-- mytable3.key1 = 11--
1.查询mytable3中是否有key1键,
2.有key1键,将mytable3表中的key1键的值改为11
-- mytable3.key2 = 22--
1.查询mytable3中是否有key2键,
2.没有key2键,查询是否有元表,
3.有元表,查询是否有__newindex元方法,
4.有__newindex元方法,且元方法为表,查询元方法的表中是否有key2键,
5.有key2键,将key2键的值修改为22
-- mytable3.key4 = 44--
1.查询mytable3中是否有key4键,
2.没有key4键,查询是否有元表,
3.有元表,查询是否有__newindex元方法,
4.有__newindex元方法,且元方法为表,查询元方法的表中是否有key4键,
5.没有key4键,对元表重复之前的赋值操作(没有元表就直接对表进行更新),
6.将key4 = 44元素添加到表newtable中
运行结果:
11 nil nil nil
nil 22 3 44
local mytable4 = setmetatable({key1 = 1},{__newindex = function(mytable4,key,value)
rawset(mytable4,key,value)
end
})
mytable4.key2 = 2
print(mytable4.key1,mytable4.key2)
解析:
1.查找mytable4中是否有key2键,
2.没有key2键,查看是否有元表,
3.有元表,元表中是否有__newindex元方法,
4.有__newindex元方法,且元方法为函数,将table,key,value作为参数,
5.执行函数
****************延伸***************
rawset:无视元表,直接对表进行更新操作
rawget:无视元表,直接对表进行查询操作
运行结果:
1 2
操作符
两表运算时
(以加为例)
local mytable5 = setmetatable({1,2,3},{__add = function (table1,table2)
for k,v in pairs(table1) do
table1[k] = table1[k] + table2[k]
end
return table1
end})
local mytable6 = {4,5,6}
local sumtable = mytable5 + mytable6
for k,v in pairs(sumtable) do
print(v)
end
解析:
1.mytable5元素为{1,2,3}且设置的元表,
2.执行“+”操作,查看元表中是否有__add键,
3.有,执行__add的函数,传入两个表为参数,返回函数返回值
运行结果:
5
7
9
元表键与运算符对应关系
键 | 运算符 |
---|---|
__add | + (加法) |
__sub | - (减法) |
__mul | * (乘法) |
__div | / (除法) |
__mod | % (模除) |
__unm | -(一元减操作符) |
__concat | …(连接符) |
__eq | == (等于) |
__lt | < (小于) |
__le | <= (小于等于) |
__call元方法
调用表时
local mytable7 = setmetatable({1,2,3},{__call = function (mytable,num)
for k,v in pairs(mytable) do
print(k,v,num)
end
end})
mytable7(12) //执行元表中的__call元方法,传入表和参数作为元方法参数
运行结果:
1 1 12
2 2 12
3 3 12
__tostring元方法
输出表时
local mytable8 = setmetatable({11,22,33,44,55,66,77,88},{__tostring = function (mytable)
local sum = 0
for k,v in pairs(mytable) do
print("key:"..k.."=====value:"..v)
sum = sum + v
end
return "sum===="..sum
end})
print(mytable8) //执行元表中的__tostring元方法
运行结果:
key:1=====value:11
key:2=====value:22
key:3=====value:33
key:4=====value:44
key:5=====value:55
key:6=====value:66
key:7=====value:77
key:8=====value:88
sum====396
总结
- __index:对表通过键查询时调用,若为表则继续查询__index表,若为函数则执行函数(table,key)
- __newindex:对表添加新键值时调用,若为表则继续添加键值给__newindex表,若为函数则执行函数(table,key,value)
- 操作符:对两个表进行运算时,执行元表(默认为被运算表的元表,若没有则为运算表的元表)中对应键的方法(table1,table2)
- __call:当将表当做函数调用时,执行该元方法(table)
- __tostring:当对表进行输出操作时实行(注:输出只能写为 print(table) 形式,不能添加其他输出)