Lua元方法__index的使用方式

__index元方法:lua语言中一种比较重要的特性,其实不光是__index,元方法还包括__newindex,__call,__add,__pairs,__sub,__mod等等还有很多,这里记录__index是因为笔者在这里经常遇到__index相关的问题,所以记录一下,以后可以随时看,元方法不一定就是方法(function),还可能是表

.我们说元这个字的意思其实就是基础的意思,那元方法是位于元表中的,下面介绍__index的几种方式

方式一:

local t1={a=1,b=2,default=10}
local t2={c=5,d=6,default=20}
t2.__index=function(self,key)
    --查看self中的数据
	for k,v in pairs(self)do
		print(k..':'..type(key)..' '..v..':'..type(v))
	end
	return rawget(self,'default')
end
setmetatable(t1,t2)
print(t1.c)


--运行结果
--[[
a:string 1:number
b:string 2:number
default:string 10:number
10
--]]
上述的描述:这里其实就是查找一下表t1当中键 ‘c’(注意这里的键其实是一个字符串,只不过在创建一个表的时候lua语言允许我们使用 {[‘c’]=1} 或者 {c=1} 这样的方式创建表中的键值对数据),发现t1中不存在’c’这个键,就会触发查找t1是否存在__index元方法(首先要查找t1是否有元表,再查找元表中是否__index这个字段对应的值),发现__index元方法是一个方法,就把t1和’c’传递到__index元方法中调用,__index的返回值就作为我们表达式t1.c的返回结果,输出10

方式二:

local t1={a=1,b=2,default=10}
local t2={c=5,d=6,default=20,__index={e=7,f=8,default=30}}
setmetatable(t1,t2)
print(t1.e)

--[[
运行结果:
7
--]]
上述是同样查找t1中不存在的键’e’,触发查找__index元方法,发现__index是一个table,就直接返回该table(__index这个table)中’e’对应的值,当然,这个是简单的情况,下面来一个稍微复杂的

方式三:

local t1={a=1,b=2,default=10}
local t2={c=5,d=6,default=20}
t2.__index={e=7,f=8}
setmetatable(t1,t2)
local t3={g=9,h=10,default = 30}
function t3:__index(key)
	for k,v in pairs(self) do
		print(k..':'..type(key)..' '..v..':'..type(v))
	end
	return rawget(self,'default')
end


--这里可以用另一种方式声明__index,也就是通常说的使用 . 和 : 的区别
--[[
function t3.__index(self,key)
	for k,v in pairs(self) do
		print(k..':'..type(key)..' '..v..':'..type(v))
	end
	return rawget(self,'default')
end
--]]
setmetatable(t2.__index,t3)
print(t1.i)

--[[
运行结果:
e:string 7:number
f:string 8:number
nil
--]]
解释一下方式三:这里查找t1中不存在的键 ‘i’(字符串键)对应的值,触发查找表t1的__index元方法,发现__index是一个table(t2.__index),就去该table中查找键’i’,发现也不存在该键,又触发了查找t2.__index这张表的__index元方法(上述的t3.__index),这次发现是一个function,就把t2.__index这个表和’i’传递进来调用该方法,这里注意传递的是t2.__index,之所以传递这个是因为我们第一次触发__index时发现__index是一个表,并且表中不存在’i’这个键,继而触发了该表的__index,所以传递的是t2.__index

下面模拟lua中的__index的实现,查找一个表table中的键key

---查找表中的键
function GetValueByKey(table,key)
    if(rawget(table,key)~=nil)then
        return rawget(table,key)
    end
    local meta = getmetatable(table)
    if(type(meta)~='table')then
        return nil
    end
    local metaIndex = rawget(meta,'__index')
    local _type=type(metaIndex)
    if(_type~='function' and _type~='table')then
        return nil
    end
    if(_type=='function')then
        return metaIndex(table,key)
    end
    return GetValueByKey(metaIndex,key)--递归
end
local t1 = {a=1,b=2 }
local t2={c=3,d=4,__index={e=5,f=6}}
setmetatable(t1,t2)
---自定义方式调用
print(GetValueByKey(t1,'e'))
---自定义方式调用
print(t1.e)

--[[
---自定义方式调用
5
---自定义方式调用
5
-]]

通过上面的模拟方法可以看出结果是一样的,上述GetValueByKey就是模拟__index机制的实现,这里使用了递归调用

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值