嚴格結構

lua-users home
wiki

我們都知道,全域變數可能是一件棘手的事(請參閱 DetectingUndefinedVariables),應該避免使用。適用於帶有名稱金鑰的函數的「嚴格結構」模式會將這些好處帶入其中

可以這樣宣告「結構」

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 = 1print(b.zz),甚至 Alice{z = 4}

因此,這為派對帶來兩件事

更強的類型也表示會拋出類型特定的斷言。

簡單地過載 __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
})

--SteveDonovan


RecentChanges · 偏好設定
編輯 · 歷史紀錄
最後編輯於 2009 年 9 月 29 日,凌晨 2:46 GMT (diff)