Lua實現C#的Get/Set屬性訪問器

雖然Lua沒有C#一樣的屬性,但是它的強大的元表和元方法能夠實現很多功能,本篇博客就介紹如何用lua的元表和原方法實現C#中的get、set屬性訪問其功能。

class.lua

class.lua是實現lua的類,我的之前博客有些過簡易版的,屬性訪問的的實現相當於在最簡易版的基礎上進行擴展,博客鏈接:Lua 實現C#中的類

local mt = {}

function class(clsName, base)
	local cls = {}
	base = base or mt
	cls.__get__ = {}
	cls.__set__ = {}
	setmetatable(cls, {__index = base})
	cls.clsName = clsName or "default"
	cls.base = base
	cls.new = function(...)
		local cls_instance = {}
		cls_instance.getset_values = {}
		for k,v in pairs(cls) do
			cls_instance[k] = v
		end
		local cls_instance_mt = {
			__index = function(t, k)
				if cls[k] then
					return cls[k]
				end
				if t.__get__[k] then
					t.__get__[k](t)
					return t.getset_values[k]
				end
				if string.sub(k, 1, 2) == "__" then
					local tmpK = string.sub(k, 3, -1)
					if t.getset_values[tmpK] then
						return t.getset_values[tmpK]
					end
				end
			end,
			__newindex = function(t, k, v)
				if t.__set__[k] then
					t.__set__[k](t, v)
					cls_instance.getset_values[k] = v
					return
				end
				if string.sub(k, 1, 2) == "__" then
					local tmpK = string.sub(k, 3, -1)
					if t.getset_values[tmpK] then
						t.getset_values[tmpK] = v
					end
				end
				rawset(t, k, v)
			end
		}
		setmetatable(cls_instance, cls_instance_mt)
		if cls_instance.onCreate then
			cls_instance:onCreate(...)
		end
		return cls_instance
	end
	return cls
end

重要擴展方式是給cls_instance添加了一個metatable,這個metatable功能有以下幾方面:

  1. 檢查xxx字段是否是__get____set__的內部字段(__get__.xxx
  2. 調用__get__ __set__ 對應的函數
  3. 修改getset_valuesxxx的值
  4. 判斷__xxx(在實例中__xxx作爲屬性的真實存儲值,如果不想通過get或者set獲取,直接instance.__xxx就不會出發對應函數)
  5. _xxx轉爲xxxgetset_values中找值並返回

test.lua

分割線之上是聲明一個類,分割線下是測試的代碼,輸出結果分別對應着p1.age = 10print(p1.__age)的每行輸出

local Person = class("Person")
Person.onCreate = function(self, name)
	self.name = name
end
Person.__get__.age = function(self)
	print(self.name, " - 屬性訪問器:get age")
end
Person.__set__.age = function(self, value)
	print(self.name, " - 屬性訪問器:set age", value)
end
-----------------------------------
local p1 = Person.new("張三")
p1.age = 10
local tmpAge = p1.age
p1.age = p1.__age + 1
print(p1.__age)

--[[
	張三	 - 屬性訪問器:set age	10
	張三	 - 屬性訪問器:get age
	張三	 - 屬性訪問器:set age	11
	11
]]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章