lua 关于__index,__newindex的理解

table存在两种行为:查询和修改(赋值),我们可以通过元方法__index和__newindex来改变table的这两种行为。

__index主要用于table的查询

table[key] 的访问过程,首先检查table表中是否存在key的字段,如果有则返回,否则检查是否有__index的元方法,没有返回nil,有则查找元方法。

__index元方法可以是不一定是一个函数,还可以是一个table。如果是一个函数,则以table和不存在的key作为参数方位该函数,

例如:__index = function(t,key)

如果是一个table时,就以相同的方式来访问这个table(即传入key访问元方法的table,如果存在则放回值,反之返回nil)

例如:__index = tab --此时会返回tab[key]的值

__index可以很好的实现具有默认值的table

function setDefaultValues(t,d)
	local mt = {__index = function() return d end}
	setmetatable(t, mt)
end
tab = {x=10,y=20}
print(tab.x ,tab.y,tab.z)	--由于没有设置元方法则为nil
setDefaultValues(tab,100)	--设置默认值(设置__index元方法)
print(tab.z)			--检查到有__index的元方法则返回默认值
但是这种设置默认值的弊端是如果很多表都需要设置默认值,则需要创建很多元表,所以更有的做法是让元表公有,其原理类似

local mt = {__index = function(t) return t.___ end}
function setDefaultValues(t,d)
	t.___= d
	setmetatable(t, mt)
e
__newindex主要用于table的更新

在书上用了简短一段话来描述__newindex


“当对table中不存在的索引赋值时,解释器就会查找__newindex元方法。如果有这个元方法,就调用这个元方法,而不是执行复制。如果这个元方法是一个table,解释器就在table中进行复制,而不是对原来的table。”


不得不说此处高能

1)当对table中不存在的索引赋值时,解释器就会查找__newindex元方法

这句话不难理解,顾名思义

2)如果有这个元方法,就调用这个元方法,而不是执行复制。

我们需要代码来验证这句话的含义:

local mt = {
	__newindex = function (table,key,value)
		print("newindex被无情地调用了")
	end
}
local t = {}
setmetatable(t, mt)
t[1] = 20
for k,v in pairs(t) do
	print(k ,v)
end
输出结果:

newindex被无情地调用了
[Finished in 0.1s]

看的出t中不存在任何值,很多blog中有这样一段替换上面的mt():

local mt = {
	__newindex = function (table,key,value)
		rawset(table, key, 2)
	end
}
输出结果:
1	2
[Finished in 0.1s]
从以上两段代码的输出我们不难看出元表中存在__newindex方法的时候对表t某个不存在的索引的赋值,直接调用的元方法,至于具体赋什么值真的是没关系

3)如果这个元方法是一个table,解释器就在table中进行复制,而不是对原来的table。

local k = {}
local mt = {
	__newindex = k
}
local t = {}
setmetatable(t, mt)
print("赋值前:")
for k,v in pairs(k) do
	print(k ,v)
end
t[1] = 20
print("赋值后:t表中的值:")
for k,v in pairs(t) do
	print(k ,v)
end

print("赋值后:k表中的值:")
for k,v in pairs(k) do
	print(k ,v)
end

输出结果:
赋值前:
赋值后:t表中的值
赋值后:k表中的值
1	20
[Finished in 0.1s]
不难看出赋值前,k是空表,赋值后k表中输出了值 key:1 value:20 而t表依旧为空。


  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值