微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

lua __index __newindex upvalue 示例

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

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

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

 

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

 

[c-sharp] view plain copy print ?
  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.正确结果

[c-sharp] view plain copy print ?
  1. function Union:init(data)  
  2.     self:initTable()  
  3.     self.data = data  
  4.     local Meta = {}  
  5.     Meta.__index = function (table, Meta)  
  6. end  

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

 

2.错误的__newindex

[c-sharp] view plain copy print ?
  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,key) if Union[key] ~= nil then return Union[key] else return self.data[key] end end Meta.__newindex = self.data setMetatable(self,Meta) end

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

    3.错误的__index

    [c-sharp] view plain copy print ?
    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) if Union[key] ~= nil then return Union[key] else return data[key] end end Meta.__newindex = function(table,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,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指向的是什么对象

    版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐