在絕大多數情況下,我們都不會用到rawget和rawset。
本文的運行環境:lua 5.3 for windows
rawset 賦值操作
rawset是在設置值的過程,進行處理,比如:當某個值改變時,觸發事件。或修改某個key為新值。
來看看rawset函數的定義
--- Sets the real value of `table[index]` to `value`, without invoking the
--- `__newindex` metamethod. `table` must be a table, `index` any value
--- different from **nil** and NaN, and `value` any Lua value.
---@param table table
---@param index any
---@param value any
function rawset(table, index, value) end
看個例子,設置過__newindex之后,就不會調用__index了?
local tb = {}
setmetatable(tb, { __index = function()
return "not find"
end })
setmetatable(tb, { __newindex = function(table, key, value)
local patchKey = "version"
if key == patchKey then
rawset(table, patchKey, "補丁值")
else
rawset(table, key, value)
end
end })
tb.version = "正常版本"
tb.date = "2018"
print(tb.version) --打印 補丁值
print(tb.server) --打印nil,不會調用__index方法了?
print(tb.date) --打印2018
經過我的測試后, 發現
---如果把__index放在__newindex之后,調用不存在值,才會調用__index方法
如果在__index在__newindex之前,則不會調用
rawget 取原始值
rawget是為了繞過__index而出現的,直接點,就是讓__index方法的重寫無效
來看看rawget函數的定義
--- Gets the real value of `table[index]`, the `__index` metamethod. `table`
--- must be a table; `index` may be any value.
---@param table table
---@param index any
---@return any
function rawget(table, index) end
編寫一個例子,測試rawget繞過__index方法
local tb = {}
setmetatable(tb, { __index = function()
return "not find"
end })
tb.version = "正常版本"
print(tb.version)
print(tb.server) ---不存在的值,調用__index方法
--rawget是為了繞過__index而出現的,直接點,就是讓__index方法的重寫無效
print(rawget(tb, "version")) --打印 正常版本
print(rawget(tb, "server")) --打印nil
__newindex
__newindex可以和rawset配合使用,也可以單獨使用
當為表分配值時,解釋器會查找__newindex方法,如果存在,則解釋器會調用它。
結合使用 __index和 __newindex,允許lua有強大的構造,從只讀表,到具有默認值的表,到面向對象編程的繼承
文檔:https://www.lua.org/pil/13.4.2.html
Lua5.3 __index要通過setmetatable設置
在lua5.3中,直接使用tableA.__index = function() end 設置,我這邊測試,並不會生效
local tempTable = { memberB = "test" }
tempTable.__index = function()
return "not find"
end
print(tempTable.memberA) --打印 nil
print(tempTable.memberB) --打印test
而通過這種方式就正常
local tempTable = { memberB = "test" }
---__index定義了當key查找不到的行為
setmetatable(tempTable, { __index = function()
return "not find"
end })
print(tempTable.memberA) --打印 not find
print(tempTable.memberB) --打印test