唯讀表格 |
|
我們可以定義下列的唯讀(常數)表格
Directions = readonlytable { LEFT = 1, RIGHT = 2, UP = 3, DOWN = 4, otherstuff = {} }
如果我們已將 readonlytable
輔助函數定義如下
function readonlytable(table) return setmetatable({}, { __index = table, __newindex = function(table, key, value) error("Attempt to modify read-only table") end, __metatable = false }); end
請注意,readonlytable
沒有傳回最初傳遞給它的表格,而是傳回代理表格。代理表格會獲得一個含有 __index
和 __newindex
後設函數的後設表格,確保代理表格的值永遠不會改變。設定 __metatable
後設函數可以防止後設表格本身遭到竄改,亦即客戶端不能透過 getmetatable
和 setmetatable
函數取得或改變後設表格。
現在,如果我們嘗試修改 Directions
的任何成員,我們會收到錯誤訊息。
> Directions.LEFT = 33
Attempt to modify read-only table
唯讀表格的成員不可改變,但我們仍可以改變唯讀表格成員的成員(除非它們也明確被製作為唯讀表格)
> Directions.otherstuff = nil -- will fail Attempt to modify read-only table > Directions.otherstuff.foo = 1 -- allowed
此外,我們仍可以使用 rawset()
和 table.insert
直接修改唯讀表格
rawset(Directions, "LEFT", 5) print(Directions.LEFT) -- prints 5 table.insert(Directions, 6) print(Directions[1]) -- prints 6
如果您真的要避免這種情況,您可以在 C 中實作唯讀表格。
此外,這種建立唯讀表格的方法會干擾 pairs
、ipairs
、next
、#
算子和其他的表格反覆運算。舉例來說,
-- prints nothing! for k,v in pairs(Directions) do print(k,v) end print(next(Directions)) -- prints nil! print(#Directions) -- prints "0"!
請參閱 GeneralizedPairsAndIpairs,瞭解相關應對方法。
原始作者:KevinBaca