元表和元方法

1.什么是元表和元方法呢?

1.元表其实也是lua中的一种表,即table,
但是它可以自定义某个表的行为,比如运算符重载、默认值查找、访问控制等
2.当一个表 t 进行某些操作(如 t1 + t2、访问 t.key)时,
Lua 会检查 t 是否有元表,并尝试调用元表中的元方法

2.举个例子 一个只读表的实现(const)

local mt = {}
--[[
__newindex 元方法是当table发生赋值的时候被调用
]]--
mt.__newindex = function()
	assert(false, "attempt change const value")
end

--[[
这里将mt设置为是a的元表,可以看出mt也是一个普通的table,
但是mt中对元方法__newindex 进行了重写,此时就改变了a表的一些行为
]]--
local a = {}
setmetatable(a, mt)

--[[
对表a进行赋值,发现表a存在着元表mt,且mt中重写了__newindex元方法,此时触发assert
]]--
a[2] = 10

3. 实现默认值

当我们需要访问一个表中的某个元素的时候,会触发元表的__index方法

--默认值
local initval = {x = 99, y = 100}

local mt = {}

--[[
下面两个写法都可以 
1.直接返回initval[下标]
2.是传入table和下标
]]
--mt.__index = initval
mt.__index = function(t, k)
	print(t)	--table: 000001AC80161E80
	return initval[k]
end



local a = {x = 88}
print(a)	--table: 000001AC80161E80
setmetatable(a, mt)
--[[
__index元方法是先从子类开始查找,它发现a中已经有了x这个下标,
然后直接返回。
当a中没有x这个下标的时候,会去查找他的元表中的__index方法。
]]
print(a.x)	--88
print(a.y)	--100

4. 实现两个table相加

集合模块

local Set = {}



local mt = {}
--[[
当两个table 相加的时候 会触发元方法__add
__add调用Set模块的并集方法
]]
mt.__add = function(a, b) return Set.union(a, b) end 

--创建一个set 并且设置元表是mt
Set.new = function(l)
	local set = {}
		
	setmetatable(set, mt);
	for k, v in pairs(l) do
		set[v] = true
	end

	return set
end

--两个集合的并集
Set.union = function (a, b)
	local set = Set.new{}

	for k, _ in pairs(a) do
		set[k] = true
	end

	for k, _ in pairs(b) do
		set[k] = true
	end

	return set
end

Set.toString = function(a)
	local str = ""
	for k, _ in pairs(a) do
		str = str .. ", ".. k
	end
	
	return str
end


return Set

调用

local set1 = Set.new({1,2,3, 99})

local set2 = Set.new({2,3,4})
print(getmetatable(set1))

print(getmetatable(set2))

--两个table相加 求出并集
local set3 = set1 + set2
print(Set.toString(set3))

5.__newindex用于表的更新操作,__index用于表的查询操作

6.绕过元方法

--上文那个只读表 可以通过这种方法来规避
rawset(a, 2, 10)
print(a[2]) --10

print(a.x)	--88
print(a.y)	--100
print(rawget(a, y))	--nil

你可能感兴趣的:(lua,c++,lua)