lua元表的理解(一) __index __newindex

        元表本质上来说是一种用来存放元方法的table 通过对应的key来得到value的值 作用就是修改一个值的行为 这种修改会覆盖原本该值可能存在的相应的预定义行为

lua中的每个值都可以有一个元表 只是table和userdata可以有各自独立的元表 而其他类型的值共享其类型所属的单一元表

lua代码只能设置table的元表 其他类型值的元表只能通过C代码设置

多个table可以共享一个通用的元表 并且每个table只能有一个元表

一、__index元方法(主要用于处理调用table中不存在的字段

lua查找表中元素的规则 

(1)先在表中查找  如果找到 返回该元素的值 找不到进行第(2)步

(2)判断该表是否具有元表 如果没有 返回nil 如果有 进行第(3)步

(3)判断元表中是否具有__index方法 如果__index为nil 则返回nil  如果__index方法是一个表 重复(1)(2)(3) 如果__index方法是一个函数 则返回该函数的返回值

function main()
	local t = {name = "hello"}
	local mt = {__index = { money = 300,}} --t中不存在money字段 但是其元表mt为其做了备胎处理
	setmetatable(t, mt)
	print("name = ".. t.name)  --hello
	print("money = "..t.money) --300
	
end
function main()
	local t = {name = "hello"}
	local mt = {__index = function()return 3000 end} 
	setmetatable(t, mt)
	print("name = ".. t.name) --hello
	print("money = "..t.money) --3000 __index是一个函数 返回其函数的返回值
	
end
father = {house = 1}
son = {car = 1}
setmetatable(son, father)
print(son.house) --首先 son中没有house字段 但是它有元表 查找其元表并没有__index方法 所以返回nil

上面刚提到的__index也可以是一个函数 当它是一个函数的时候 lua会调用此函数 table和键会作为参数传递给函数

__index元方法查看表中元素是否存在 如果不存在 返回结果为nil 如果存在 则由__index返回结果

二、__newindex 用来table的更新

t = {}

local mt = {__newindex = function(table,key,value)
							print("key = "..key)
							print("value = "..value)
							key = value
						end
						}
function main()
	local t = {a = "hello world"}
	setmetatable(t, mt)
	print("before xiugai")
	print(t.a)
	print("after xiugai")
	t.a = "zhangyin"
	print(t.a)
	
	t.b = "say hello"
	print(t.b) -- nil 进入了元表 但是并未赋值  因为给未定义的key赋值时会调用元方法不去赋值
	
end
main()

__newindex 用于table更新时 需要注意 假如我现在要修改的key并不存在于表中 但是此表有元表 继而调用元表里的__newindex方法 但是由于key不存在于表中 所以在调用元方法时 不会给其赋值 比如上述代码中的b 修改之前 元表中无__index方法 所以b的值返回nil  修改后 由于B未在表中有定义 所以并没有执行__newindex中的 key = value 是因为调用函数时要传入表table 要修改的key 以及对应的value 但是由于key不存在于表中 所以__newindex不进行赋值 所以使用__newindex的规则一 如果__newindex是一个函数 则在给table中不存在的字段赋值时 会调用这个函数 并且赋值不成功

function test()
	local smartMan = {name = "none"}
	local other = {name = "hello everyone  i am so weiqu"}
	
local  t1 = {}
local mt = {__index = smartMan,
            __newindex = other
 }

 setmetatable(t1, mt)
 
 print(" before other = " .. other.name); --hello everyone  i am so weiqu
 t1.name = "yyyyyyyyyy";
 print(" after other = " .. other.name); ---yyyyyyyyyy
 print(" t1 = " .. t1.name); ---none
 
end
test()

首先 给t1的name赋值时 name字段不存在 发现他有元表 只能通过元表里的__index找到了smartMan里的name字段 值为none

但是给表里不存在的字段赋值 此时_-newindex是一个表  所以修改了other表的值 所以使用__newindex规则二  如果__newindex是一个table,则在给table不存在的字段赋值时,会直接给__newindex的table赋值

以上两个例子总结一下:

如果__newindex是一个函数 则在给table中不存在的字段赋值时 会调用这个函数 并且赋值不成功

如果__newindex是一个table,则在给table不存在的字段赋值时,会直接给__newindex的table赋值

猜你喜欢

转载自blog.csdn.net/weixin_41966991/article/details/88862445
今日推荐