lua 打印对table中的字符赋值时的堆栈日志
今天日常码代码时遇到一个问题,对一个表的字段赋值时,后期使用时 不知何时,又在哪里改变了这个table中的字段的值,代码又很多,一行一行找很麻烦,我们可以使用 lua 中的元方法实现 当给table中的一个字段赋值时 我们就打印赋值堆栈日志 我们首先要了解 元方法 __index 和 __newindex
1. __index
lua中的元方法 __index 有 A ,B两个表, B是A的元表 , 当调用 A.a 的时候访问了A中不存在的字段 ,如果有元表,会调用 元表(B)中的__index 如果元表中没有 __index 方法,返回 nil 如例1
--例 1
A = {
}
B = {
a = 1
}
--设置元表
setmetatable(A, B)
例2实现实现了预期的效果
--例 2
A = {
}
B = {
a = 1
}
B.__index = B
--设置元表
setmetatable(A, B)
__index 是一个表的时候 ,会去表中找到访问的字段。 当__index 是一个函数时会调用这个函数。
A = {
}
B = {
a = 1
}
B.__index = function(t, k)
print("调用了__index元方法")
end
--设置元表
setmetatable(A, B)
虽然调用了__index 但是还是返回了 nil, 在元方法中 return 需要的值即可
B.__index = function(t, k)
print("调用了__index元方法")
return 1
end
2. __newindex
lua中的__newindex 元方法 跟 __index 元方法类型 __index 是访问一个不存在的字段时调用 __newindex 是对表中不存在的字段赋值时调用 __newindex 用于对表中不存在的字符赋值,赋值,赋值,__index 是访问, 访问, 访问
__newindex 是一个表时 对这个表赋值
A = {
}
B = {
}
B.__newindex = B
--设置元表
setmetatable(A, B)
A.name = "B"
print(A.name)
print(B.name)
这就是所谓的隔山打牛
当 __newindex 是一个方法时
A = {
}
B = {
}
B.__newindex = function(t, k, v)
print("调用了 __newindex 元方法")
end
--设置元表
setmetatable(A, B)
A.name = "B"
print(A.name)
print(B.name)
如果要设置值的话 不用 直接 t[k] = v (t 的元表中不能有 __newindex 元方法) 这样会进入死循环 ,使用 rawset(t, k, v) 忽略 __newindex引用
A = {
tag = "a"
}
B = {
tag = "b"
}
B.__newindex = function(t, k, v)
print("调用了 __newindex 元方法")
print(t.tag)
rawset(t,k,v)
end
--设置元表
setmetatable(A, B)
A.name = "B"
print(A.name)
print(B.name)
3.我们了解了 __index 和 __newindex 来实现我们的对表赋值时, 就打印日志是从何处赋值
local assignment = function(monitor)
-- monitor 需要监控的表
if monitor == nil or type(monitor) ~= "table" then
return
end
-- 赋值,访问 数据都存入cacheTable表,
-- 这样的话 monitor表,一直是没有任何字段的,每次访问、赋值都会执行元方法 __index、__newindex
local cacheTable = {}
local _index = function(t, k)
return cacheTable[k]
end
local _newindex = function(t,k,v)
print("字段名赋值 = " .. k, debug.traceback())
rawset(cacheTable, k, v)
end
setmetatable(monitor, {__index = _index, __newindex = _newindex})
end
A = {}
assignment(A)
A.name = "张三"
A.sex = "男"
A.age = "26"
print(A.name)
print(A.sex)
print(A.age)