Getters and setters in Squirrel class instances

After reading the recent post on metamethods, we figured we could use them quite well to ‘protect’ our data structures.
In practice we’re using it to define a “data” property in a class that can be “get” and “set” just as normal keys but that exhibit a different behaviour for get and set (with protection build into the ‘set’. Code to include in the class definition below. (_data is the class private field, _validate() a private class method for validating the supplied value)
`
function _get(key)
{
if (key == “data”) return _data; // use switch() statement when more getters defined
throw("Cannot get nonexistant getter : " + key);
}

function _set(key,value)
{
if (key == “data”) {
if (_validate(value)) {
// do whatever else you want to do when data is set
_data = data;
}
else
throw(“Cannot set '” + key “’ : bad data structure”);
}
throw("Attempt to set nonexistant setter : " + key);
}
There is a caveat though. If you do that, you cannot access global table keys anymore within such class instance as it will treat it as a non-existant getter or setter. One can say that as a matter of good programming practice you shouldn't use global keys in class instances, but it's also true for the system defined ones such as getroottable itself or time() etc.. This can be easily solved by adjusting the code (_get() example only) in this way.
function _get(key)
{
if (key in ::getroottable()) return ::getroottable()[key];
if (key == “data”) return _data;
throw("Cannot get nonexistant getter : " + key);
}
`
or, off course, use the :: operator systematically in your class code when accessing a global key…

BTW, it also works for classes derived from such class, but to my experience only when the definition of _get() is in the base class. I didn’t succeed redefining it in the derived class yet (but didn’t try hard either). Anybody willing to give it a try ?

People can off course still screw things up by using the _data field directly, but that’s a matter of coding discipline in the team.

As this forum has helped me a lot in the past, I just thought this could be of interest for others. I would have found it quite helpfull as an example in the metamethods documentation (hint, hint :slight_smile: )

Are there any other known or expected caveats with this approach ???

Good luck with metamethods. I’ve dabbled with them and found them too frustrating. But, I think they can be powerful, if carefully managed.

The biggest issue I have had with them is that the Agent VM can’t interrupt them. If you have processing intensive code (1000 squirrel bytecode operations, which unfortunately there are no tools to count) in the same call stack as a metamethod, be prepared for your agent to be halted and restarted…

yeah, I saw that. I’m strictly limiting the use to accessing only one sensitive field in the class (the underlying _data field) with some simple validation code.
I did notice that you apparently cannot override metamethods, which makes it less practical in the case of derived classes.