【Lua】元表(Metatable)

记录学习过程

创建日期:2019-04-14

元表(Metatable)

在 Lua table 中我们可以访问对应的key来得到value值,但是却无法对两个 table 进行操作。
因此 Lua 提供了元表(Metatable),允许我们改变table的行为,每个行为关联了对应的元方法。

例如,使用元表我们可以定义Lua如何计算两个table的相加操作a+b。
当Lua试图对两个表进行相加时,先检查两者之一是否有元表,之后检查是否有一个叫"__add"的字段,若找到,则调用对应的值。"__add"等即时字段,其对应的值(往往是一个函数或是table)就是"元方法"。

mytable = {"Lua","Java","C#","C++"} --普通表

mymetatable = {} --元表   元表扩展了普通表的行为

mytable =setmetatable(mytable,mymetatable)--把 mymetatable 设为 mytable 的元表

print(mytable)
print(getmetatable(mytable))
print(mymetatable)

tab = setmetatable({"Lua","Java","C#","C++"} , {__metatable="lock"} )
print(getmetatable(tab))
--使用__metatable可以保护元表,禁止用户访问元表中的成员或者修改元表。

输出

table: 00DAA2B0
table: 00DAA828
table: 00DAA828
lock

__index元方法
当你通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的__index 键。如果__index包含一个表格,Lua会在表格中查找相应的键。

t = setmetatable({key1 = "value1"},{__index={key2="value2"}})

print(t.key1,t.key2,t.key3)--value1	value2	nil

如果__index包含一个函数的话,Lua就会调用那个函数,table和键会作为参数传递给函数。
__index 元方法查看表中元素是否存在,如果不存在,返回结果为 nil;如果存在则由 __index 返回结果。

t = setmetatable({key1="value1"},{
	__index=function(tab,key)
		if key == "key2" then
			return "value2"
		else
			return nil
		end
	end
})

print(t.key1,t.key2,t.key3)--value1	value2	nil

或通过索引查找

t = setmetatable({"value1","value2"},{
__index=function(tab,key)
	if(key>=10) then
		return "value"
	end
end
})

print(t[1],t[2],t[3],t[11])--value1	value2	nil	value

__newindex 元方法
__newindex当我们对表的数据进行修改的时候,当我们修改的是一个新的索引的时候才会起作用 当我们给表添加新的键值对的时候,起作用

mytable = {key1="value1"}
mymetatable={
__newindex = function(tab,key,value)
		rawset(tab,key,value)
		--tab[key]=value--这样会死循环
	end
}

t = setmetatable(mytable,mymetatable)

print(t.key1,t.key2)--value1	nil

t.key2="value2"
print(t.key1,t.key2)--value1	value2

为表添加操作符

__add元方法

--计算表的元素个数
function table_maxn(t)
	local mn=0
	for k,v in pairs(t) do
		if mn<k then
		mn=k
		end
	end
	return mn
end

mytable = setmetatable({1,2,3},{
	__add=function(tab,newtab)
		for i=1,table_maxn(newtab) do
			table.insert(tab,table_maxn(tab)+1,newtab[i])
		end
		return tab
	end
})

sectable ={4,5,6}
--两表相加
mytable = mytable + sectable

for k,v in ipairs(mytable) do
	print(k,v)
end

输出

1	1
2	2
3	3
4	4
5	5
6	6
元方法对应的运算符
__add+
__sub-
__mul*
__div/
__mod%
__unm-
__concat
__eq==
__lt<
__le<=

__call 元方法
当一个表被当做函数调用时,就会调用__call

mytable = setmetatable({10}, {
  __call = function(mytable, str)
	return str
  end
})

print(mytable("haha")) --haha

__tostring 元方法
__tostring 元方法用于修改表的输出行为

mytable = setmetatable({ 10, 20, 30 }, {
  __tostring = function(mytable)
    sum = 0
    for k, v in pairs(mytable) do
                sum = sum + v
        end
    return "表所有元素的和为 " .. sum
  end
})
print(mytable)--表所有元素的和为 60
相关推荐
©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页