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