嚴格結構 |
|
可以這樣宣告「結構」
struct.Alice { x = 1; y = 2; }
並這樣實例化
a = Alice {x = 10, y = 20}
或
b = Alice {x = 10} -- y will be set to 2
嘗試存取 a 和 b 的未知欄位將會產生錯誤,例如 a.z = 1
或 print(b.zz)
,甚至 Alice{z = 4}
。
因此,這為派對帶來兩件事
Alice
,而非「一個 x 和 y 為數字的函數」更強的類型也表示會拋出類型特定的斷言。
簡單地過載 __tostring
也會提供類型的特定字串表述,例如「Alice #23」,以進行偵錯。
可以用 (適合的代理函數表) 來強制執行欄位指派中的動態類型檢查,但這當然會產生執行時間成本。
-- struct.lua --- defining a struct constructor --- local struct_mt = { -- instances can be created by calling the struct object __call = function(s,t) local obj = t or {} -- pass it a table (or nothing) local fields = s._fields -- attempt to set a non-existent field in ctor? for k,v in pairs(obj) do if not fields[k] then s._error_nf(nil,k) end end -- fill in any default values if not supplied for k,v in pairs(fields) do if not obj[k] then obj[k] = v end end setmetatable(obj,s._mt) return obj end; } -- creating a new struct triggered by struct.STRUCTNAME struct = setmetatable({},{ __index = function(tbl,sname) -- so we create a new struct object with a name local s = {_name = sname} -- and put the struct in the enclosing context _G[sname] = s -- the not-found error s._error_nf = function (tbl,key) error("field '"..key.."' is not in "..s._name) end -- reading or writing an undefined field of this struct is an error s._mt = { _name = s._name; __index = s._error_nf; __newindex = s._error_nf; } -- the struct has a ctor setmetatable(s,struct_mt) -- return a function that sets the struct's fields return function(t) s._fields = t end end })