项目中有个公会对象,数据大部分存在data中,之前都是 u.data.point这样访问,太麻烦了。
于是通过设置__index 使之可以直接访问属性,u.point。
但是还是不能直接改属性,u.point = 4,所以再设置了__newindex。
在设置了setmetatable之后,不能直接给u添加新属性,因为设置了__newindex,新的属性将直接加到u.data中的。
- 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()
通过修改__index和__newindex会获得不同的结果。
1.正确结果
- 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
3    103    3    3
 4    103    4    4
 4    103    103    103
 4    104    104    104
2.错误的__newindex
- 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
3    103    3    3
 4    103    4    4
 4    103    103    103
 104    103    103    103
3.错误的__index
- 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
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)         ifk ~= "hp" then         object[k] = v         end     end     }     setmetatable(proxy,mt)     returnproxy 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指向的是什么对象