Hi there! Thanks for your kind words.
Let me start by saying that I am not a huge fan of getters/setters in Lua. In other languages, I can accept them; for example in ruby, they are integrated in the language's message-passing mechanism.
But in Lua they are extra syntactic sugar, and risk making things more "magical" (unexpected to someone unfamiliar with the code).
That said, your approach is a good approximation at implementing properties. I would suggest some changes though.
- I would put the properties-related code in a mixin, so that it can be easily reused by multiple classes without having to do "the metatable dance" on every class.
- I would still require getter and setter methods. That way, if someone (like me) doesn't want to use properties, they have the option to use the "old fashioned" methods
- Given the previous point, I would build the properties by convention: if there is a set_xxx method, then xxx is setable via obj.xxx = too. Similarly, if there is a get_xxx method, then xxx is gettable via obj.xxx. This way you would not even need the 'setters' or 'getters' variables.
That would give us this mixin:
Code: Select all
-- properties.lua
local Properties = {}
function Properties:__index(k)
return self['get_' .. k]
end
function Properties:__newIndex(k, v)
local fn = self['set_' .. k]
if fn then
fn(self, v)
else
rawset(self, k, v)
end
end
end
return Properties
Usage:
Code: Select all
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
r.name = 'peter'
print(r.name) -- peter