1.元表基础
1.基础
1.userdata类型和table类型的每个变量都可以设置一个元表
2.number、string等每个类型可设置一个元表,类型的所有变量共用这个元表
3.只有table在lua里可以设置元表,其他都必须在 C 语言里设置元表
4.string类型默认已经设置元表了,通过 getmetatable(‘aa’) 查看
2.元表设置和读取
local a = {}
local b = {}
local meta = {}
查看变量元表
getmetatable(变量)
设置变量元表
1.正常设置 setmetatable(a, meta)
2.设置元表是自己 setmetatable(a, a)
3.元表相互设置出错
setmetatable(a, b)
setmetatable(b, a)
2.元方法
local a = {}
local b = {}
local meta = {}
local c = a + b --__add
setmetatable(a, meta) --__metatable
print(a) --__tostring
print(a.xx) --__index
a.xx = 5 --__newindex
1.数学运算符重载
__add 元方法
说明:两个table变量是不能做算术运算的比如,如 tab1+tab2,通过运算符重载实现两个table算术运算
用途:运算符重载
local a = {}
local b = {}
local meta = {}
meta.__add = function(p1, p2)
print('p1 == a')
print('p2 == b')
return 100
end
setmetatable(b, meta)
local c = a + b --c==100
1.先检查a变量是否有元表和元方法__add,如果a有不再检查b了,如果a没有再去检查b
2.形参p1对应变量a,p2对应变量b
3.变量a或b只要有一个有元表并且有元方法__add,另一个可以是任何类型table其他算术运算重载(*、/、-)类似 “+”(__add) 法
2. __tostring
local b = {}
local meta = {}
meta.__tostring = function(p)
return "aa"
end
setmetatable(b, meta)
print(b) --打印:aa
1.执行 print 检查 b 是否有元表并且有元方法 __tostring
2.有打印元方法 __tostring 返回的值
3. __metatable
表 b 已经设置过元表了,不能给表 b 再次设置元表
不能得到表 b 的元表
local b = {}
local meta = {}
meta.__metatable = '不能获得元表了'
setmetatable(b, meta)
print(getmetatable(b)) -- 打印:不能获得元表了
setmetatable(b, {}) -- 报错
0.前提:变量 b 有元表并且 __metatable 字段不为nil
1.getmetatable 得到变量 b 元表,打印 __metatable 字段内容
2.setmetatable 设置变量 b 元表,变量 b 已经有元表了不能再设置元表了
4. __index
触发:访问表 b 里不存在的字段 xx
local b = {}
local meta = {}
setmetatable(b, meta)
-- meta.__index = function(tab, key)
-- return 'aaa'
-- end
meta.__index = {xx='aaa'}
print(b.xx) --打印:aaa
1.查找表 b 的元表 meta, meta 对应的字段 __index
2.如果 __index 对应的是函数, b.xx 等于函数返回值
3.如果 __index 对应的是table, b.xx 去 table 里查找 xx 字段返回对应的值
4.读取表没有的字段 rawget(table, key)(不考虑元表) 不会执行 __index
5. __newindex
触发:给表 b 添加新的字段 xx 并给它赋值
用途:不希望给表 b 在增加新的字段
local b = {}
local meta = {}
setmetatable(b, meta)
meta.__newindex = function(table, key, value)
print('执行了')
end
b.xx = 'bbb'
print(b.xx) --打印:nil
1.给表 b 的新字段 xx 赋值
2.执行表 b 的元表 meta 对应的字段 __newindex 的方法
3.表添加新字段并赋值 rawset(table, key, value)(不考虑元表) 不会执行 __newindex