(浅)Lua学习笔记_关于元表

  • setmetatable(table,metatable): 对指定 table 设置元表(metatable),如果元表(metatable)中存在 __metatable 键值,setmetatable 会失败。(会返回table)
  • getmetatable(table): 返回对象的元表(metatable)。

__index 元方法

  •  如果包含表格

  当你通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的__index 键。如果__index包含一个表格,Lua会在表格中查找相应的键

1 tabMETA ={ temp = 1}
2 
3 tabA = setmetatable( {} ,{ __index = tabMETA} );        
4 
5 print(tabA.temp)
6 
7 输出: 1
  •   如果包含函数

  如果__index包含一个函数的话,Lua就会调用那个函数,table和键会作为参数传递给函数。

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

1 mytable = setmetatable({key1 = "value1"}, { __index = { key2 = "metatablevalue" } })
2 print(mytable.key1,mytable.key2)
3 
4 输出:value1    metatablevalue
  •  总结

注意!

Lua 查找一个表元素时的规则,其实就是如下 3 个步骤:

  • 1.在表中查找,如果找到,返回该元素,找不到则继续
  • 2.判断该表是否有元表,如果没有元表,返回 nil,有元表则继续。
  • 3.判断元表有没有 __index 方法,如果 __index 方法为 nil,则返回 nil;如果 __index 方法是一个表,则重复 1、2、3;如果 __index 方法是一个函数,则返回该函数的返回值。

该部分内容来自作者寰子:https://blog.csdn.net/xocoder/article/details/9028347


__newindex 元方法

 __newindex 元方法用来对表更新,__index则用来对表访问 。

  •  如果是函数

  如果你尝试给一个不存在的索引进行赋值,解释器就会查找__newindex 元方法:如果是函数调用这个函数不进行赋值操作。

1 tab = setmetatable({},{__newindex= function(tab,key,value) print("注意:尝试给不存在的索引赋值!") end})
2 tab[1] = 1 --给不存在的索引赋值
3 print(tab[1])
4  
5 输出: 注意:尝试给不存在的索引赋值!    nil 

但是,如果我想要进行赋值操作该怎么办呢?  

是这样写吗?

1 tab = setmetatable({},{function(tab,key,value) 
2     tab[key] = value
3 end})

上述写法是错误的,会导致栈溢出,原因是因为函数中的“tab[key] = value”在执行时,又会调用该表的__newindex元方法,一层一层的无限调用下去,导致栈溢出。

正确写法如下:

1 tab = setmetatable({},{function(tab,key,value) 
2      rawset(tab,key,value)
3 end})

这里用了rawset函数来赋值,rawset的参数为(表,键,值) rawset(tab,key,value)

  •   如果是表

  如果你尝试给一个不存在的索引进行赋值,解释器就会查找__newindex 元方法:如果是表则在此表中赋值,不对原表进行操作。

1 tab2 = {}
2 tab1 = setmetatable({},{__newindex = tab2})
3 tab1[996]="不要996" 4 print(tab1[996]) 5 print(tab2[996]) 6 7 输出:nil 不要996 --出现在了tab2中

猜你喜欢

转载自www.cnblogs.com/guoyujam/p/12199378.html
今日推荐