項目中有個公會對象,數據大部分存在data中,之前都是 u.data.point這樣訪問,太麻煩了。
于是通過設置__index 使之可以直接訪問屬性,u.point。
但是還是不能直接改屬性,u.point = 4,所以再設置了__newindex。
?
在設置了setmetatable之后,不能直接給u添加新屬性,因為設置了__newindex,新的屬性將直接加到u.data中的。
?
[c-sharp] view plaincopyprint?
Union?=?{??????data?=?nil,??????dirty?=?nil,??}??---?生成新的對象??function?Union:new(o)??????o?=?o?or?{}??????setmetatable(o,self)??????self.__index?=?self??????return?o??end??---?初始化Union數據??function?Union:init(data)??????self:initTable()??????self.data?=?data??????local?meta?=?{}??????meta.__index?=?function?(table,?key)??????????if?Union[key]?~=?nil?then??????????????return?Union[key]??????????else??????????????return?self.data[key]??????????end??????end??????meta.__newindex?=?function(table,key,?value)??????????self.data[key]?=?value??????end??????setmetatable(self,?meta)??end??function?Union:initTable()??????if?self.data?==?nil?then??????????self.data?=?{}??????end??????if?self.dirty?==?nil?then??????????self.dirty?=?{}??????end??end??function?Union:print()??????print(self.point,?self.data.point)??end??function?pt()??????print(data1.point,?data2.point,?u.point,?u.data.point)??end??u?=?Union:new()??data1?=?{point?=?3}??data2?=?{point?=?103}??u:init(data1)??pt()??u.point?=?4??pt()??u.data?=?data2??pt()??u.point?=?104??pt()??
Union = {data = nil,dirty = nil,
}
--- 生成新的對象
function Union:new(o)o = o or {}setmetatable(o,self)self.__index = selfreturn o
end
--- 初始化Union數據
function Union:init(data)self:initTable()self.data = datalocal meta = {}meta.__index = function (table, key)if Union[key] ~= nil thenreturn Union[key]elsereturn self.data[key]endendmeta.__newindex = function(table,key, value)self.data[key] = valueendsetmetatable(self, meta)
end
function Union:initTable()if self.data == nil thenself.data = {}endif self.dirty == nil thenself.dirty = {}end
end
function Union:print()print(self.point, self.data.point)
end
function pt()print(data1.point, data2.point, u.point, u.data.point)
end
u = Union:new()
data1 = {point = 3}
data2 = {point = 103}
u:init(data1)
pt()
u.point = 4
pt()
u.data = data2
pt()
u.point = 104
pt()
?
?
?
通過修改__index和__newindex會獲得不同的結果。
?
1.正確結果
[c-sharp] view plaincopyprint?
function?Union:init(data)??????self:initTable()??????self.data?=?data??????local?meta?=?{}??????meta.__index?=?function?(table,?key)??????????if?Union[key]?~=?nil?then??????????????return?Union[key]??????????else??????????????return?self.data[key]??????????end??????end??????meta.__newindex?=?function(table,key,?value)??????????self.data[key]?=?value??????end??????setmetatable(self,?meta)??end??
function Union:init(data)self:initTable()self.data = datalocal meta = {}meta.__index = function (table, key)if Union[key] ~= nil thenreturn Union[key]elsereturn self.data[key]endendmeta.__newindex = function(table,key, value)self.data[key] = valueendsetmetatable(self, meta)
end
3??? 103??? 3??? 3
4??? 103??? 4??? 4
4??? 103??? 103??? 103
4??? 104??? 104??? 104
?
2.錯誤的__newindex
[c-sharp] view plaincopyprint?
function?Union:init(data)??????self:initTable()??????self.data?=?data??????local?meta?=?{}??????meta.__index?=?function?(table,?key)??????????if?Union[key]?~=?nil?then??????????????return?Union[key]??????????else??????????????return?self.data[key]??????????end??????end??????meta.__newindex?=?self.data??????setmetatable(self,?meta)??end??
function Union:init(data)self:initTable()self.data = datalocal meta = {}meta.__index = function (table, key)if Union[key] ~= nil thenreturn Union[key]elsereturn self.data[key]endendmeta.__newindex = self.datasetmetatable(self, meta)
end
3??? 103??? 3??? 3
4??? 103??? 4??? 4
4??? 103??? 103??? 103
104??? 103??? 103??? 103
3.錯誤的__index
[c-sharp] view plaincopyprint?
function?Union:init(data)??????self:initTable()??????self.data?=?data??????local?meta?=?{}??????meta.__index?=?function?(table,?key)??????????if?Union[key]?~=?nil?then??????????????return?Union[key]??????????else??????????????return?data[key]??????????end??????end??????meta.__newindex?=?function(table,key,?value)??????????self.data[key]?=?value??????end??????setmetatable(self,?meta)??end??
function Union:init(data)self:initTable()self.data = datalocal meta = {}meta.__index = function (table, key)if Union[key] ~= nil thenreturn Union[key]elsereturn data[key]endendmeta.__newindex = function(table,key, value)self.data[key] = valueendsetmetatable(self, meta)
end
3??? 103??? 3??? 3
4??? 103??? 4??? 4
4??? 103??? 4??? 103
4??? 104??? 4??? 104
?對象A在內部可以修改HP.外部對象只能訪問對象A的HP,不能修改.
這東西其實可以用__index和__newindex來實現.
__index指向對象A,這樣就可以訪問;
__newindex重寫,修改hp的話,就禁止.就可以完成他的需求.
下面給出簡單的代碼:
| function cannotModifyHp(object) ????local proxy = {} ????local mt = { ????????__index = object, ????__newindex = function(t,k,v) ????????if k ~= "hp" then ????????object[k] = v ????????end ????end ????} ????setmetatable(proxy,mt) ????return proxy end ?? object = {hp = 10,age = 11} function object.sethp(self,newhp) ????self.hp = newhp end ?? o = cannotModifyHp(object) ?? o.hp = 100 print(o.hp) ?? o:sethp(111) print(o.hp) ?? object:sethp(100) print(o.hp) |
function cannotModifyHp(object)
????local proxy = {}
????local mt = {
????????__index = object,
????__newindex = function(t,k,v)
????????if k ~= "hp" then
????????object[k] = v
????????end
????end
????}
????setmetatable(proxy,mt)
????return proxy
end
object = {hp = 10,age = 11}
function object.sethp(self,newhp)
????self.hp = newhp
end
??
o = cannotModifyHp(object)
??
o.hp = 100
print(o.hp)
??
o:sethp(111)
print(o.hp)
??
object:sethp(100)
print(o.hp)
?
這里影響程序的不同結果是upvalue導致的。
由于一般程序中有可能動態改data。所以建議用function設置__index和__newindex,尤其注意各個不同函數中self指向的是什么對象
總結
以上是生活随笔為你收集整理的lua __index __newindex upvalue 示例的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。