Lua __index __newindex元表方法学习

本文深入探讨Lua语言中元表的使用,特别是rawset、rawget、__index和__newindex的方法。通过实例代码,详细分析setmetatable的多次调用对元表的影响,解答为何设置__newindex后可能不再调用__index。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在学习Lua语言的元表和元方法章节中,各种网上收例子,便于理解学习。

看到一篇很好的博客,讲到了 lua 的 rawset,rawget,index,newindex的使用,具体博客见下面链接:

作者:@qingqing-zhao
本文为作者原创,转载请注明出处:https://www.cnblogs.com/zhaoqingqing/archive/2018/11/28/10032249.html

在开头的一段代码中,作者留一下一个问题:

设置过__newindex之后,就不会调用__index了?

然后我将作者的例子,自己在linux  lua5.1 环境下执行了一遍,并加些log,且能属性table中的具体元素,这样就能看到是否在执行下面这一句时,真没进到 __index函数中去:

print(tb.server)

测试代码如下:

local tb = {}
setmetatable(tb, { __index = function()
    print("__index 000000")
    return "not find"
end })

setmetatable(tb, {

    __newindex = function(table, key, value)
    local patchKey = "version"
    print("__newindex 11111111111")
    if key == patchKey then
        print("__newindex 2222222222222")
        rawset(table, patchKey, "patch value")
    else
        print("__newindex 3333333333333")
        rawset(table, key, value)
    end
end })

print("111 table tb:")
PrintTable(tb)

tb.version = "normal version"
tb.date = "2018"
print(tb.version) --打印 补丁值
print("\n")

print("111111111-----")
print(tb.server) --打印nil,不会调用__index方法了?
print("222222222-----")

print("\n")
print(tb.date)  --打印2018

print("222 table tb:")
PrintTable(tb)

执行结果如下:

111 table tb:
  {
  }
__newindex 11111111111
__newindex 2222222222222
__newindex 11111111111
__newindex 3333333333333
patch value


111111111-----
nil
222222222-----


2018
222 table tb:
  {
   version = patch value
   date = 2018
  }

的确如作者所说,在 执行下面这一行,真没有调用 __index方法,

print(tb.server) --打印nil,不会调用__index方法了?

根据作者提出的问题,我再网上查了老半天,也没有看到能解释这种现象的。

但就在午饭时,不经意看代码发现,作者的代码上面,执行了两次 setmetatable操作,会不会第二次将第一次的 setmetatable

中的 __index 给覆盖掉了? 是不是lua的 table 只能设置一次setmetatable?

如是,我将__index和__newindex移到了一起,在一个 setmetatable进行设置,代码如下:

local tb = {}
-- setmetatable(tb, { __index = function()
    -- print("__index 000000")
    -- return "not find"
-- end })

setmetatable(tb, { 
    __index = function()
	print("__index 000000")
	return "not find"
    end,

    __newindex = function(table, key, value)
    local patchKey = "version"
	print("__newindex 11111111111")
    if key == patchKey then
	print("__newindex 2222222222222")
        rawset(table, patchKey, "patch value")
    else
	print("__newindex 3333333333333")
        rawset(table, key, value)
    end
end })

print("111 table tb:")
PrintTable(tb)

tb.version = "normal version"
tb.date = "2018"
print(tb.version) --打印 补丁值
print("\n")

print("111111111-----")
print(tb.server) --打印nil,不会调用__index方法了?
print("222222222-----")

print("\n")
print(tb.date)  --打印2018

print("222 table tb:")
PrintTable(tb)

 再次执行结果如下:

111 table tb:
  {
  }
__newindex 11111111111
__newindex 2222222222222
__newindex 11111111111
__newindex 3333333333333
patch value


111111111-----
__index 000000
not find
222222222-----


2018
222 table tb:
  {
   version = patch value
   date = 2018
  }

修改为如上,代码,则作者提出的问题就不会出现,

print(tb.server)  就会调用 _index 的函数,打印: not find

但提出了新问题:

lua 中table的setmetatable是不是只能设置一次? 多次设置是不是只有最后的一次设置才有效?

这些问题,目前还在查找和验证中,

非常感谢那篇博主的文章,让我学到不少东西,加深理解元表。

同时发现书中所说的字符串的元表都是相同的一个,验证也确实是:

local str00 = "Hello"
local str01 = "World"
print(getmetatable(str00))
print(getmetatable(str01))

输出结果:

table: 0x14eb490
table: 0x14eb490

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值