1. 程式人生 > >Lua rawget rawset newindex 函式定義和例子

Lua rawget rawset newindex 函式定義和例子

在絕大多數情況下,我們都不會用到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.
[email protected]
table table [email protected] index any [email protected] 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.
[email protected]
table table [email protected] index any [email protected] 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