元表和元方法是lua进行面向对象编程的很重要的方法,所以 花时间研究了一下。
(元方法,是在设置元表之后在元表中查找的方法,使用之前一定要setmetatable 或者用getmetatable检查是否有元表)
__index方法(主要是查找时)
当调用一个table的索引值不存在时,lua会查找该table的__index方法,__index方法可以是函数,也可是一个table;
举例:
local mt = {}
一 、--__index传入的是函数
mt.__index = function (table,key)
print("key = ",key)
end
local t = {my = "i have one"}
print("这是输出1",t.myAdd)
--[LUA-print] 这是输出1 nil
setmetatable(t,mt)
print("这是输出2",t.myAdd)
--[LUA-print] key = myAdd --这句打印说明 程序进入了__index方法中查找
--[LUA-print] 这是输出2 nil -- 但是__index方法中还是没有这个索引值
二 、-- __index 传入的是table
local mt = {}
local mtTable = { meta = "this is prevalue"}
mt.__index = mtTable
local t = {my = "i have one"}
print("这是输出1",t.meta) --[LUA-print] 这是输出1 nil (普通查找key不存在 打印为空)
setmetatable(t,mt)
print("这是输出2",t.meta)--[LUA-print] 这是输出2 this is prevalue (设置元表后,对于不存在的key进入元表查找,元表中返的table有于是输出)
__newindex元方法(主要是赋值时)
当给table中不存在的索引赋值时,Lua会去查找该table的__newindex方法。__newindex同样可以传入函数 或者 一个table
举例:
一 、--__newindex传入的是函数
local mt = {}
mt.__newindex = function (table,key,value)
print("key值是:",key)
print("value值是:",value)
end
local t = {aa = "hehe"}
setmetatable(t,mt)
print(t.aa)
--输出表中已有的索引aa
[LUA-print] hehe ----- 只有一句打印,没有进入元方法中,因为t中有aa索引
--为表中不存在的索引进行赋值
t.bb = "wawa"
print(t.bb)
[LUA-print] key值是: bb
[LUA-print] value值是: wawa
-- 上面两句打印说明进入到了元方法,并且打印了索引 和值
[LUA-print] nil -- 这句打印非常重要,可以发现t.bb还是空值,说明上面的赋值操作并没有起作用,因为只是进入了元表中,但元表没有进行赋值,所以打印还是nil
--打印完整的t
printt(t)
[LUA-print] ["aa"] = "hehe", -- 从这个打印可以看出,t 现在还是只有一个索引,并没有赋值成功。
二、--__newindex传入的是table
local mt = {}
local mtTable = {}
mt.__newindex = mtTable
local t = {}
setmetatable(t,mt)
print(t.newkey,mt.newkey)
[LUA-print] nil nil
因为两个t都是空 所以打印都是nil
-- 这里给 t 添加索引并赋值
t.newkey = "this is new value"
print(t.newkey,mtTable.newkey)
[LUA-print] nil this is new value
但是打印的结果是 t 并没有赋值成功 反而是mtTable赋值成功。
这是因为给 table 不存在的索引赋值时,进入了他的 元方法,而在元方法中的table 就有了这个键值对。(如果没有设置元表则会直接赋值)
而原先的 t 则 不会受影响。