在lua中我们无法对两个table进行操作,例如两个表相加、相减、串连等操作。因此 Lua 提供了元表(Metatable)和元方法,允许我们操作改变table,每个操作关联了对应的元方法。

  • 设置元表
    setmetatable(mytable,mymetatable) 对指定 mytable设置元表(mymetatable)。
mytable={}
mymetatable={}
setmetatable(mytable,mymetatable) 
temp=getmetatable(mytable) 
print(temp)
print(mymetatable)
  • 特定操作__tostring
    __tostring 元方法用于修改表的输出行为。
mytable={}
mymetatable={
	__tostring=function(t)
	   return t.name
	end

}
mytable.name="2222"
setmetatable(mytable,mymetatable) 
print(mytable)
  • 特定操作__call
    __call 元方法在 Lua 表作为方法被调用触发。以下实例演示了计算表中元素的和。
mytable={1.2,2,3}
mymetatable={
	__call=function(mytable,newtable)
	   sum=0
	   for k,v in pairs(mytable) do
	   	sum=sum+v
	   end
	    for k,v in pairs(newtable) do
	   	sum=sum+v
	   end
	   return sum
	end

}
setmetatable(mytable,mymetatable) 
print(mytable({4,5,6}))
  • 特定操作__add
    __add元方法两表相加操作。
mytable={}
mytable={1,2,3}
mymetatable = {
   __add=function(mytable,newtable)
		 	for i = 1, #(newtable) do
     		 	table.insert(mytable, #(mytable)+1,newtable[i])
    		end
		 return mytable
	end
}
setmetatable(mytable,mymetatable) 
 temp={4,5,6}+mytable
 for k,v in pairs(temp) do
 	print(k,v)
 end
  • __index 元方法
    当你通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的__index 键**。如果index包含一个表格,Lua会在表格中查找相应的键。
mytable={}
mymetatable={}
mymetatable.age=1
setmetatable(mytable,mymetatable) 
print(mytable.age)

打印出来是nil,指定元表的__index元方法后

mytable={}
mymetatable={}
mymetatable.__index=mymetatable
mymetatable.age=1
setmetatable(mytable,mymetatable) 
print(mytable.age)

能够得到我们预期的值1

  • __newindex 元方法
    __ newindex 元方法用来对表更新,__index则用来对表访问 。
    当你给表的一个缺少的索引赋值,解释器就会查找__newindex 元方法:如果存在则调用这个函数而不进行赋值操作。
mytable={name="223"}
mymetatable={}
newTable={}
mymetatable.__newindex=newTable
setmetatable(mytable,mymetatable) 
mytable.age=15
print(mytable.name)
print(newTable.age)
  • 其他元方法
    __sub: 减法(-)运算。行为类似于加法运算。
    __mul: 乘法(*)运算。行为类似于加法运算。
    __div: 除法(/)操作。行为类似于加法运算。
    __mod: 模(%)运算。行为类似于加法运算。
    __pow: 取幂(^)。行为类似于加法运算。
    __unm: 否定(一元-)运算。行为类似于加法运算。
    __idiv: 楼层划分(//)操作。行为类似于加法运算。
    __band: 按位AND(&)运算。行为与加法运算类似,不同之处在于,如果任何操作数既不是整数,也不是可强制转换为整数的浮点数,则Lua会尝试使用元方法(请参见第3.4.3节)。
    __bor: 按位OR(|)操作。行为类似于按位与运算。
    __bxor: 按位异或(二进制~)运算。行为类似于按位与运算。
    __bnot: 按位NOT(一元~)运算。行为类似于按位与运算。
    __shl: 按位左移(<<)操作。行为类似于按位与运算。
    __shr: 按位右移(>>)操作。行为类似于按位与运算。
    __concat: 串联(…)操作。行为与加法运算类似,不同之处在于,如果任何操作数既不是字符串也不是数字(始终可强制转换为字符串),则Lua会尝试使用元方法。
    __len: 长度(#)操作。如果对象不是字符串,Lua将尝试其元方法。如果存在元方法,Lua会以对象作为参数来调用它,并且调用的结果(总是调整为一个值)是操作的结果。如果没有元方法,但是对象是一个表,则Lua使用表长度操作(请参见第3.4.7节)。否则,Lua会引发错误。
    __eq: 等于(==)运算。行为与加法操作类似,只是Lua仅在被比较的值是两个表或两个完整的用户数据且它们本来就不相等时才尝试元方法。调用结果始终转换为布尔值。
    __lt: 小于(<)运算。行为类似于加法运算,不同之处在于Lua仅在所比较的值既不是数字也不是字符串时才尝试使用元方法。此外,调用的结果总是转换为布尔值。
    __le: 等号(<=)运算。行为类似于小于操作。
    __index: 索引访问操作table[key]。当table不是表或key中不存在此事件时,就会发生此事件table。在的元表中查找元值table。
    此事件的元值可以是函数,表或具有__index元值的任何值。如果它是一个函数,则使用table和key作为参数调用它,并且调用的结果(调整为一个值)是操作的结果。否则,最终结果是使用索引此元值的结果key。此索引是常规索引,不是原始索引,因此可以触发另一个__index元值。
    __newindex: 索引分配table[key] = value。与index事件类似,此事件在table不是表或keyin中不存在时发生table。在的元表中查找元值table。
    与索引一样,此事件的元值可以是函数,表或具有__newindex元值的任何值。如果它是一个功能,它被称为用table,key以及value作为参数。否则,Lua将使用相同的键和值对该元值重复索引分配。此分配是常规的,而不是原始的,因此可以触发另一个__newindex元值。每当__newindex调用元值时,Lua都不执行原始赋值。如果需要,元方法本身可以调用rawset 进行分配。
    __call: 呼叫操作func(args)。当Lua尝试调用非函数值(即func不是函数)时,会发生此事件。元方法在中查找func。如果存在,则将元方法func作为第一个参数来调用,然后是原始调用(args)的参数。调用的所有结果都是操作的结果。这是唯一允许多个结果的元方法。