现在的位置: 首页 > 综合 > 正文

lua __index __newindex upvalue 示例

2017年12月11日 ⁄ 综合 ⁄ 共 5184字 ⁄ 字号 评论关闭

项目中有个公会对象,数据大部分存在data中,之前都是 u.data.point这样访问,太麻烦了。

于是通过设置__index 使之可以直接访问属性,u.point。

但是还是不能直接改属性,u.point = 4,所以再设置了__newindex。

 

在设置了setmetatable之后,不能直接给u添加新属性,因为设置了__newindex,新的属性将直接加到u.data中的。

 

  1. Union = {  
  2.     data = nil,  
  3.     dirty = nil,  
  4. }  
  5. --- 生成新的对象  
  6. function Union:new(o)  
  7.     o = o or {}  
  8.     setmetatable(o,self)  
  9.     self.__index = self  
  10.     return o  
  11. end  
  12. --- 初始化Union数据  
  13. function Union:init(data)  
  14.     self:initTable()  
  15.     self.data = data  
  16.     local meta = {}  
  17.     meta.__index = function (table, key)  
  18.         if Union[key] ~= nil then  
  19.             return Union[key]  
  20.         else  
  21.             return self.data[key]  
  22.         end  
  23.     end  
  24.     meta.__newindex = function(table,key, value)  
  25.         self.data[key] = value  
  26.     end  
  27.     setmetatable(self, meta)  
  28. end  
  29. function Union:initTable()  
  30.     if self.data == nil then  
  31.         self.data = {}  
  32.     end  
  33.     if self.dirty == nil then  
  34.         self.dirty = {}  
  35.     end  
  36. end  
  37. function Union:print()  
  38.     print(self.point, self.data.point)  
  39. end  
  40. function pt()  
  41.     print(data1.point, data2.point, u.point, u.data.point)  
  42. end  
  43. u = Union:new()  
  44. data1 = {point = 3}  
  45. data2 = {point = 103}  
  46. u:init(data1)  
  47. pt()  
  48. u.point = 4  
  49. pt()  
  50. u.data = data2  
  51. pt()  
  52. u.point = 104  
  53. pt()  

 

 

 

通过修改__index和__newindex会获得不同的结果。

 

1.正确结果

  1. function Union:init(data)  
  2.     self:initTable()  
  3.     self.data = data  
  4.     local meta = {}  
  5.     meta.__index = function (table, key)  
  6.         if Union[key] ~= nil then  
  7.             return Union[key]  
  8.         else  
  9.             return self.data[key]  
  10.         end  
  11.     end  
  12.     meta.__newindex = function(table,key, value)  
  13.         self.data[key] = value  
  14.     end  
  15.     setmetatable(self, meta)  
  16. end  

3    103    3    3
4    103    4    4
4    103    103    103
4    104    104    104

 

2.错误的__newindex

  1. function Union:init(data)  
  2.     self:initTable()  
  3.     self.data = data  
  4.     local meta = {}  
  5.     meta.__index = function (table, key)  
  6.         if Union[key] ~= nil then  
  7.             return Union[key]  
  8.         else  
  9.             return self.data[key]  
  10.         end  
  11.     end  
  12.     meta.__newindex = self.data  
  13.     setmetatable(self, meta)  
  14. end  

3    103    3    3
4    103    4    4
4    103    103    103
104    103    103    103

3.错误的__index

  1. function Union:init(data)  
  2.     self:initTable()  
  3.     self.data = data  
  4.     local meta = {}  
  5.     meta.__index = function (table, key)  
  6.         if Union[key] ~= nil then  
  7.             return Union[key]  
  8.         else  
  9.             return data[key]  
  10.         end  
  11.     end  
  12.     meta.__newindex = function(table,key, value)  
  13.         self.data[key] = value  
  14.     end  
  15.     setmetatable(self, meta)  
  16. 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指向的是什么对象

抱歉!评论已关闭.