我试图添加对属性声明的自动支持,以便类获得自动为它们生成的getter和setter。我使用中间类库作为类的基础。我已经定义了一个处理属性创建的根类。但是,在测试中,只有根类的直接子类才能正常工作。另一些则在中间代码([string "local middleclass = {..."]:82: stack overflow)中给出堆栈溢出错误。
我的代码是:
local CBaseObject=class('CObjectBase');
function CBaseObject:initialize()
self._init=true;
end;
function CBaseObject:finalize()
self._init=false;
end;
function CBaseObject:_getter_setter(v)
return v;
end;
function CBaseObject:_gen_prop_cache()
rawset(self,'_properties',rawget(self,'_properties') or {});
end;
function CBaseObject:__index(k)
print('GET',k);
self:_gen_prop_cache();
local prop=self._properties[k];
if prop~=nil
then
local getter=self[prop[2] or '_getter_setter'];
return getter(self,prop[1]);
else return nil;end;
end;
function CBaseObject:__newindex(k,v)
print('ME',self.class.name);
print('SET',k,v);
self:_gen_prop_cache();
local prop=self._properties[k];
if prop==nil and self._init or prop
then
if prop==nil then prop={};self._properties[k]=prop;end;
local vv=prop[1];
if type(v)=='table' and #v<4
then
for i=1,3 do prop[i]=v[i];end;
else
prop[1]=v;
end;
local setter=self[prop[3] or '_getter_setter'];
prop[1]=setter(self,prop[1],vv);
else
rawset(self,k,v);
end;
end;考试课程:
local cls=CBaseObject:subclass('test');
function cls:initialize()
self.class.super.initialize(self);
self.health={1000,'_gethealth','_sethealth'};
self.ammo=100;
self:finalize();
end;
function cls:_sethealth(value,old)
print('WRITE:',value,old);
if value<0 then return old;else return value;end;
end;
function cls:_gethealth(value)
print('READ:',value);
return value/1000;
end;
local cls2=cls:subclass('test2');
function cls2:initialize()
self.class.super.initialize(self);
self.ammo=200;
self:finalize();
end;
function cls2:_sethealth(value,old)
print('WRITE_OVERRIDEN:',value,old);
return value;
end;
local obj=cls2(); --change this to cls() for working example.
obj.health=100;
obj.health=-100;
print(obj.health,obj._properties.health[1]);
print(obj.ammo,obj._properties.ammo[1]);我使用https://repl.it/languages/lua运行我的代码。所以,问题是,我做什么都是正确的方法吗?是否有可能以一种与使用的库兼容的更简单的方式添加属性支持?或者我应该用另一个,然后呢?
编辑:经过实验,我发现错误应该归咎于构造self.class.parent.<method>(<...>)。我用实际的父类替换了所有这些事件。这似乎是唯一的问题,在那之后,代码开始无错误地工作到目前为止。
发布于 2017-01-30 03:24:48
Enriqueía(中产阶层的创建者)启发了我,我认为这是一个不错的中产阶级的实现getter/setter的方法。他建议创建和使用混和。
在测试/使用这个混合配方时,我做了一些小的更改。目前我使用的是这样的一个:
-- properties.lua
local Properties = {}
function Properties:__index(k)
local getter = self.class.__instanceDict["get_" .. k]
if getter ~= nil then
return getter(self)
end
end
function Properties:__newindex(k, v)
local setter = self["set_" .. k]
if setter ~= nil then
setter(self, v)
else
rawset(self, k, v)
end
end
return Properties您必须为属性创建function get_*和function set_* (或者根据您的意愿修改上面的字符串模式)。
示例:
local class = require('middleclass')
local Properties = require('properties')
local Rect = class('Rect'):include(Properties)
function Rect:initialize(x, y, w, h)
self.x = x
self.y = y
self.w = w
self.h = h
end
function Rect:get_right()
return self.x + self.w
end
function Rect:set_right(right)
self.x = self.x + right - self.right
end
r = Rect:new(10,10, 100, 100)
print(r.right) -- 110
print(r:get_right()) -- 110
r.right = 200
print(r.right) -- 200
print(r.x) -- 100通过这种方式,您可以在任何您想拥有属性的类中使用这个混音,只需在其上创建get_*和set_*函数。
不过,他还说:
在Lua,我并不是一个狂热的getter/setters粉丝。在其他语言中,我可以接受它们;例如,在ruby中,它们被集成到语言的消息传递机制中。 但在Lua中,它们是额外的语法糖,可能会使事情变得更“神奇”(对于不熟悉代码的人来说是意想不到的)。
性能注意事项:但是,值得一提的是,与示例一样,使用__index函数会严重影响代码的性能(如果与__index表相比的话)。就我个人而言,经过一段时间使用getter和setter(由于我的Python偏见),我决定显式地写东西,不再依赖它们。当然,这取决于性能对您的代码是否重要。
https://stackoverflow.com/questions/39886333
复制相似问题