title: middleclass: add getter-setter support for properties
body: <p>I'm trying to add automatic support for property declarations, so that a class gets getters and setters generated automatically for them. I use the middleclass library as a base for classes. I've defined a root class that handles property creation. However, in tests, only an immediate subclass of the root class works properly. Others give me stack overflow error deep inside the middleclass code (<code>[string "local middleclass = {..."]:82: stack overflow</code>).</p>
  
  <p>My code is:</p>
  
  <pre><code>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&lt;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;
  </code></pre>
  
  <p>Test classes:</p>
  
  <pre><code>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&lt;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]);
  </code></pre>
  
  <p>I used <a href="https://repl.it/languages/lua" rel="nofollow">https://repl.it/languages/lua</a> to run my code. So, the questions is, is what I do even the right approach? Is it possible to add property support in an easier way compatible with the used library? Or should I use another, and what then?</p>
  
  <p>EDIT: after experimenting I found out that the construct <code>self.class.parent.&lt;method&gt;(&lt;...&gt;)</code> is to blame for the error. I replaced all such occurrences by actual parent classes. That was the only problem, it seems, after that the code started to work error-free so far.</p>