通常,lua中的每个值都有一套预定义的操作集合。例如,可以将数字相加,可以连接字符串,还可以在table中插入一对key-value等。但是我们无法将两个table相加,无法对函数作比较,也无法调用一个字符串。
可以通过元表来修改一个值得行为,使其在面对一个非预定义的操作时执行一个指定的操作。例如,加上a和b都是table,通过元表可以定义如何计算表达式a+B.当lua试图将两个table相加时,它会先检查两者之一是否有元表,然后检查该元表是否有一个叫_add的字段。如果lua找到了该字段,就调用该字段对应的值,这个值也就是所谓的“元方法”,它应该是一个函数、
lua中的每个值都有一个元表,table和userdata可以有各自独立的元表,而其他类型的值则共享其类型所属的单一元表。Lua在创建新的table时不会创建元表:
t= {}
print(getmetatable(t))
可以使用setmetatable来设置或修改任何table的元表:
t1={}
setmetatable(t,t1)
assert(getmetatable(t)==t1)
任何table都可以作为任何值得元表,而一组相关的table也可以共享一个通用的元表,此元表描述了它们共同的行为。一个table甚至可以作为它自己的元表,用于描述其特有的行为,总之,任何搭配形式都是合法的。在lua中,只能设置table的元表,若要设置其他类型的值得元表,则必须通过C代码来完成。标准的字符串程序为所有的字符串都设置了一个元表,而其他类型在默认情况中都没有元表:print(getmetatable("hi"))
算术类的元方法:
Set ={}
function Set.new(l)
local set={}
for _,v in ipairs(l) do set[v]=true end
return set
end
function Set.union(a,b)
local res = Set.new{}
for k in pairs(a)do res[k]=true end
for k in pairs(b) do res[k]=true end
return res
end
function Set.intersection(a,b)
local res =Set.new{}
for k in pairs(a) do
res[k]=b[k]
end
end
function Set.tostring(set)
local l ={}
for r in pairs(set) do
l[#l +1] = e
end
return "{"..table.concat(l,",").."}"
end
function Set.print(s)
print(Set.tostring(s))
end