Lua中的元表和元方法学习笔记
元表(metatable)是Lua里每种类型的值的默认操作方式的集合,例如,数字可以加减乘除、字符串可以连接合并、table可以插入一对key-value值、函数可以被调用等等,这些操作都遵循其预定义的行为来执行。
而值的默认操作方式不是一成不变的,可以通过元表来修改其行为表现,或者是新定义一些默认没有的操作。例如,当两个table相加时,Lua会检查它们之间的元表里是否有"__add"这个函数,如果定义有这个函数,则调用这个函数来执行一次加法操作。
这里,相加这个操作的函数名--"__add"是元表的键名(元表的键名也称之为事件(event),一般以2个下划线"_"开头),而"__add"函数则是这个相加操作的元方法(metamethod)。对于值的操作,Lua都将其关联上一个被称作事件的指定健,当Lua需要对一个值发起这些操作中的一个时,它会去检查值的元表里是否有对应事件。如果有,则键名对应的值(元方法)将控制Lua怎样去执行这个操作。
getmetatable-获取元表
Lua里每个值都有一个元表。table类型和userdata类型的值可以有各自独立的元表,而其他类型的值则是公用其类型所预先定义的元表。例如,可以用getmetatable来获取一个字符串的元表:
a="justatest" print(getmetatable(a))
上面的操作会输出"table:0x7fa8614080f0"的table,里面包含着预先定义给字符串的操作方法,其内容结构如下:
-__index-sub[function:0x7fee39408050]
-upper[function:0x7fee394080a0]
-len[function:0x7fee39407ec0]
-gfind[function:0x7fee39407e20]
-rep[function:0x7fee39407fb0]
-find[function:0x7fee39407d30]
-match[function:0x7fee39407f60]
-char[function:0x7fee39407c90]
-dump[function:0x7fee39407ce0]
-gmatch[function:0x7fee39407e20]
-reverse[function:0x7fee39408000]
-byte[function:0x7fee39407c40]
-format[function:0x7fee39407d80]
-gsub[function:0x7fee39407e70]
-lower[function:0x7fee39407f10]
Lua在创建新的table时不会创建元表,因此想调用getmetatable函数获取其元表的话,只会返回一个nil值。
tbl={}
print(getmetatable(tbl))
setmetatable-修改元表
对于上面所说的新创建的table是空元表的问题,可以用setmetatable来修改其元表:
tbl={}
t1={key="val"}
setmetatable(tbl,t1)
print(getmetatable(tbl))
对于上面所说的2个table相加的情况,可以给table添加一个__add的元方法就可以进行相加操作:
t1={"a","b","c","d"}
t2={5,6,7,8,9}
mt={}
mt.__add=function(a,b)
localtbl={}
localret={}
fork,vinpairs(a)dotbl[v]=trueend
fork,vinpairs(b)dotbl[v]=trueend
fork,vinpairs(tbl)do
table.insert(ret,k)
end
returnret
end
setmetatable(t1,mt)
setmetatable(t2,mt)
t=t1+t2
fork,vinpairs(t)doprint(v)end