元表和元方法

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值