Lua_Metatable元表

--元表,元表附属于表,用于表的扩展,是更底层的东西。
--元表的作用多种多样,其中一个就是可以在对普通表操作时方法的重载,用于扩展,因此一般情况下定义好后不需要再次修改元表。
----比如让两个表进行相加,如果没有元表的话直接相加编译器会报错的。
----还有就是用print输出表时,是直接输出这个表的内存块名,用了元表就可以很方便的输出表的元素

tab1 = {1,2,3,4,5,6}
met1 = {}
tab2 = setmetatable(tab1,met1)
met2 = getmetatable(tab1)

print(tab1,tab2) --输出:table: 00A395A0	table: 00A395A0
print(met1,met2) --输出:table: 00A39A50	table: 00A39A50

----------------------------------------------------

-- __metatable关键字,可以保护元表,禁止用户访问元表中的成员或者修改元表。

tab = setmetatable({"Lua","Java","C#","C++"} , {__metatable="lock"} )
print(getmetatable(tab)) --输出:lock

---------------------------------------------------------

--__index关键字,用于访问普通表不存在的Key时,所调用元表的扩展方法

tab1 = {1,2,3,4,5,6}
met1 = {
	__index = function(tab,key)
		print("tab",tab)
		print("调用了元表的__index方法")
		table.insert(tab1,key) --table表插入方法,参数1:table,参数2:[index]位置,参数3:value
	end}
tab2 = setmetatable(tab1,met1)
met2 = getmetatable(tab1)

function OnContainTab(tab,value)
	for k,v in pairs(tab) do
		if v == value then
			print("搜索到目标 k:"..k.." v:"..v)
			return true
		end
	end
	return false
end

print("tab1",tab1) --输出:tab1	table: 00B196D0
print("表的个数为: "..table.getn(tab1)) --输出:表的个数为: 6
print(tab1[100]) --输出:tab	table: 00B196D0 | 调用了元表的__index方法 | nil
print("表的个数为: "..table.getn(tab1)) --输出:表的个数为: 7
OnContainTab(tab1,100) --输出: 搜索到目标 k:7 v:100

---------------------------------------------------------------

-- __newindex关键字,在table添加新的数据时,会调用这个

tab1 = {1,2,3,4,5,6}
local met1 = {
		__newindex = function(tab,key,value) --元表关键字支持函数
		print("普通表中未找到Key:"..key)
		rawset(tab,key,value) --添加新的键值对
		--table.insert(tab,key,value)  --添加新的键值对
	end
	}

function OnContainTab(tab,value)
	for k,v in pairs(tab) do

		if v == value then
			print("搜索到目标 k:"..k.." v:"..v)
			return true
		end
		if k == value then
			print("搜索到目标 k:"..k.." v:"..v)
			return true
		end
	end

	return false
end

newtab1 = setmetatable(tab1,met1)

newtab1[7] = "qi" --输出:普通表中未找到Key:7
OnContainTab(newtab1,7) --输出:搜索到目标 k:7 v:qi


tab2 = {1,2,3,4,5,6}
tab3 = {}
local met2 = {
		__newindex = tab3 --元表关键字还支持Table
	}

newtab2 = setmetatable(tab2,met2)

newtab2[7] = "qi" --由于元表__newindex指向了tab3,因此当普通表tab2的索引查不到Key时,会自动地赋值给tab3
print(tab2[7]) --输出:nil
print(tab3[7]) --输出:qi 

---------------------------------------------------

-- add关键字,在table进行数学操作符时,进行扩展
tab1 = {1,3,5}
tab2 = {2,4,6}

local met1 = {
		__add = function(tab_1,tab_2) --add关键字,参数1:tab1,参数2:tab2
		for k,v in pairs(tab_2)do
			table.insert(tab_1,v)
		end
		return tab_1
	end
	}

newtab1 = setmetatable(tab1,met1)

tab3 = tab1+tab2

for k,v in pairs(tab3) do
	print(k,v) --输出:1	1 | 2	3 | 3	5 | 4	2 | 5	4
end

----------------------------------------------------

-- __call关键字,可把table当做函数来使用
tab1 = {1,3,5}

local met1 = {
		__call =
		function(tab,...) 使用"...",用于处理所有参数
			print(...)
			return tab
		end
	}

newtab1 = setmetatable(tab1,met1)
newtab1(123,123123) --输出:123	123123

------------------------------------------------------

-- __tosting关键字,用于直接打印table时,所扩展的方法

tab1 = {"一","二","三"}
local met1 = {
		__tostring =
		function(tab)
			local string = ""
			for k,v in pairs(tab) do
				string = string..k.." "..v.."|"
			end
			return string
		end
	}

newtab1 = setmetatable(tab1,met1)

print(newtab1) --元表没有__tostring关键字则输出:table: 00DB9438,加了则输出:1 一|2 二|3 三|

猜你喜欢

转载自blog.csdn.net/Le_Sam/article/details/85201429