__index和__newindex以及相关应用

元表

有必要先说下元表,英文名:metatable。开始见到这个词,并不是很能理解元表的含义。于是查询meta-前缀的含义:一般科学技术领域,metaXXX意思为XXX of/about XXX。英文解释:is a prefix meaning “referring to itself.” 简单来说就是复合。放在lua语言中的metable:table about table。也就是说一个table的元表是为这个table服务的。原则上,lua中每一个值都可以有一个元表,只不过除了表以外的值赋予元表必须通过C代码或调试库完成(因为有风险)。每一个table都可以有一个元表,最多只能有一个。

元方法

元方法是和元表紧紧相连的产物。__index和__newindex就是两个比较常用的元方法

__index

local t = {}
print(t.name)
--> nil

上面的代码,毫无疑问,最后输出nil,因为t中并没有name的字段。

local mt = {
	__index = {
			name = "张三"
		}
}
local t = {}
setmetatable(t, mt)--设置t的元表为mt
print(t.name)
--> 张三

为啥这次会输出张三?分析一下:首先去找t中的name字段,发现找不到,此时并没有停止操作,而是去t中的元表中__index字段中去寻找name字段,找到,输出。
简单来说,__index元方法的作用就是当引用一个不存在的字段时,会自动的去这个table的元表中的__index字段里去引用。__index可以是一个table,也可以是一个函数。看下面

local names = {
	name = "张三"
}
local mt = {
	__index = function(_, key) --key表示缺失的字段,_表示那张表,这里就是t
		print("缺失的字段为:" .. key)
		return names[key]
	end
}
local t = {}
setmetatable(t, mt)--设置t的元表为mt
print(t.name)
--> 缺失的字段为:name
--> 张三

__newindex

简单来说,newindex就是用来捕捉并屏蔽赋值不存在的字段的操作。
通过以下例子来感受一下 捕捉和屏蔽两个功能

local mt = {
	__newindex = function(_, key,  value) --key表示缺失的字段,_表示那张表,这里就是t
		print("捕捉到您正在给" .. key .. "赋值为:"  .. value)
	end
}
local t = {}
setmetatable(t, mt)--设置t的元表为mt
t.name = "ss"
print(t.name)
-->捕捉到您正在给name赋值为:ss
-->nil

分析一下:当想要赋值给t中不存在的字段name时,__newindex顺利捕捉到这个操作,并且把该赋值操作屏蔽,最后该字段还是为nil。

尝试用__index和__newindex写一张只读表

试想一下你是一个主程,不希望手下的新人修改你的代码,那么你就可以写一张只读表。

function ReadOnly(t)
	local mt = {
		__index = t,
		__newindex = function(t, k, v)
			print("捕捉到您正在给" .. k.. "赋值为:"  .. v)
		end
	}
	local proxy = {}
	setmattable(proxy, mt)
	return proxy
end
names = ReadOnly({name1 = "张三", name2 = "李四", name3 = "王五"})
print(names.name1)
names.name2 = "赵六"
-->张三
-->捕捉到您正在给name2 赋值为:赵六

分析一下,proxy就是一个代理,当赋值names中的name2字段时,实际上是赋值它的代理proxy中的name2字段,proxy中当然不存在name2,于是就被proxy的元表中的__newindex捕捉并屏蔽。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值