一、概念
- 任何表变量都可以作为另一个表变量的原表
- 任何表变量都可以有自己的元表(父表)
- 当子表进行一些特定操作时,会执行元表中的内容
二、设置原表
setmetable(子表,元表)
meta = {}
myTable = {}
setmetable(myTable,meta)
三、 特定操作: __tostring
当子表要被当作字符串使用时,会默认调用这个元表中的__tostring方法
meta = {
__tostring = function()
return "元表方法"
end
}
mytable = {}
setmetable(myTable,meta) --关联元表
print(mytable) --把子表当字符串使用,调用元表tostring方法
输出:元表方法
当__tostring中有参数时,会默认把自己传进去
meta = {
__tostring = function(t)
return t.name --需要已知表中有这个属性
end
}
myTable = {
name = "我是子表"
}
setmetable(myTable,meta) --关联元表
print(mytable)
输出:我是子表
四、 特定操作: __call
- 当子被当作一个函数来使用时,会默认调用__call中的内容
- 仅有当元表中实现了__call方法,子表才能被当作函数来使用
- 当希望传参数时,默认第一个参数是调用者自己
meta = {
__call = function(a,b) --参数a是调用者(子表)自己,b才是是子表传的参数
print(a,b)
end
}
myTable = {
name = "我是子表"
}
setmetable(myTable,meta) --关联元表
mytable("子表参数")
输出:我是子表 子表参数
五、 特定操作: __index和__newIndex
- __index:当子表中找不到某一个属性时,回到元表中__index指定的表去找属性,可以向上嵌套
meta = {
name = "元表"
}
mytTable = {}
setmetable(myTable,meta)
print(myTable.name)
输出结果: nil
------------------------------------分割线-----------------------------------------
meta = {
name = "元表"
}
--_ _indexd 的赋值建议卸载外部,避免出问题
meta.__index = meta --元表的__index指向自己本身,可以指向其他表
mytTable = {}
setmetable(myTable,meta)
print(myTable.name)
输出结果: 元表
- __newIndex:当赋值时,如果赋值一个不存在的索引,那么会把这个值赋值到newIndex所指的表中,不会修改自己(没有newIndex所指的表,那么在自己表中新增)
meta = {}
meta.__newIndex = {}
mytTable = {}
setmetable(myTable,meta)
mytTable.name = "子表"
print(myTable.name, myTable.__newIndex.name)
输出结果: nil 子表
六、 其他操作
getmetatable(表):获取元表rawget(表,属性):会忽略元表__index指向的表,在自己身上找这个属性的值meta = { name = "元表"} meta.__index = meta mytTable = {} setmetable(myTable,meta) print(myTable.name) print(rawget(mytTable,"name")) 输出结果: 元表 nilrawset(表,属性,值):会忽略__newIndex指向的表,只给自己的表中属性赋值meta = {} meta.__newIndex = {} mytTable = {} setmetable(myTable,meta) mytTable.name = "子表" print(myTable.name, myTable.__newIndex.name) 输出结果: 子表 nil