Minimalistic approach to OOP by instantiating objects directly from user-defined classes. Works with Lua 5.1+ and LuaJIT.
The module returns a table, which can be called in order to create a new object:
local Object = require('Object')
local myobject = Object()You can optionally pass in a user-defined class, as well as varargs that will be proxied to the constructor (if defined):
local Object = require('Object')
local MyClass = {
_init = function(self, a, b)
print(a, b)
end,
}
local myobject = Object(MyClass, "hello", "world") -- hello worldMyClass:_init(...)MyClass:_get_XXX()MyClass:_set_XXX(value)MyClass:_on_XXX(...)Object:rawget(key)Object:get(key)Object:rawset(key, value, publish)Object:set(key, value)Object:publish(event, ...)Object:subscribe(event, callback)Object:unsubscribe(event, callback)Object:once(event, callback)
The class constructor. The arguments passed here are directly proxied from the
Object(class, ...) call.
local Object = require('Object')
local MyClass = {}
function MyClass:_init(a, b)
self.sum = a + b
end
local myobject = Object(MyClass, 1, 2)
print(myobject.sum) -- 3Class defined getter on property XXX. When defined, accessing myobject.XXX
will return the result from the getter. You can use Object:rawget to bypass getters.
local Object = require('Object')
local MyClass = {}
function MyClass:_get_myprop()
return 42
end
local myobject = Object(MyClass)
print(myobject.myprop) -- 42Class defined setter on property XXX. When defined, assigning
myobject.XXX = myvalue will call the setter with myvalue. You can use
Object:rawset to bypass setters. change_XXX events
are not automatically published after custom setters and must be published manually.
local Object = require('Object')
local MyClass = {}
function MyClass:_set_myprop(value)
self:rawset('myprop', value + 10)
end
local myobject = Object(MyClass)
myobject.myprop = 42
print(myobject.myprop) -- 52Class defined event handler. When defined, gets called whenever the event XXX is published.
local Object = require('Object')
local MyClass = {}
function MyClass:_on_change_myprop(value)
print('myprop has changed to: ' .. tostring(value))
end
function MyClass:_on_myevent()
print('emitted myevent')
end
local myobject = Object(MyClass)
myobject.myprop = 42 -- myprop has changed to: 42
myobject:publish('myevent') -- emitted myeventGets the value indexed by key from the object without invoking getters. First
checks for key in the object, then searches for key in the class, and
finally defaults to indexing Object directy.
local Object = require('Object')
local MyClass = {}
function MyClass:_get_myprop(value)
return 42
end
local myobject = Object(MyClass)
myobject.myprop = 24
print(myobject.myprop) -- 42
print(myobject:rawget('myprop')) -- 24The getter function for the object. Calling this is equivalent to simply accessing the key directly.
local Object = require('Object')
local myobject = Object()
-- equivalent
print(myobject.mykey)
print(myobject:get('mykey'))Sets the index of key to value without invoking setters. If publish is
set to true, publishes a change_XXX event (where XXX is the value of key)
that passes the new and old values.
local Object = require('Object')
local MyClass = {}
function MyClass:_set_myprop(value)
self:rawset('myprop', value + 10)
end
local myobject = Object(MyClass)
myobject.myprop = 42
print(myobject.myprop) -- 52
myobject:rawset('myprop', 42)
print(myobject.myprop) -- 42local Object = require('Object')
local MyClass = {}
function MyClass:_on_change_myprop(new_value, old_value)
print(new_value, old_value)
end
local myobject = Object(MyClass)
myobject:rawset('myprop', 42, true) -- 42 nil
myobject:rawset('myprop', 24, true) -- 24 42The setter function for the object. Calling this is equivalent to simply assigning the key directly.
local Object = require('Object')
local myobject = Object()
-- equivalent
myobject.mykey = 42
myobject:set('mykey', 42)Invokes all subscribers of event, passing in
the provided varargs to each subscription callback.
local Object = require('Object')
local myobject = Object()
myobject:subscribe('myevent', function(a, b)
print(a + b)
end)
myobject:publish('myevent', 1, 2) -- 3Adds a callback to be called whenever event is published.
Returns the callback itself (useful for unsubscribing).
The same function cannot be subscribed to the same event multiple times (no duplicate subscriptions).
local Object = require('Object')
local myobject = Object()
myobject:subscribe('myevent', function(a, b)
print(a + b)
end)
myobject:publish('myevent', 1, 2) -- 3Removes a callback from being called when event is published.
local Object = require('Object')
local myobject = Object()
local subscription = myobject:subscribe('myevent', function(a, b)
print(a + b)
end)
myobject:publish('myevent', 1, 2) -- 3
myobject:unsubscribe('myevent', subscription)
myobject:publish('myevent', 1, 2) -- nothing prints!Adds a callback to be called the next time event is published.
This callback only fires once and then immediately unsubscribes itself. Similarly to
Object:subscribe, this returns the subscribed function
and can be removed via Object:unsubscribe (note that
the subscribed function is not the same as callback). Unlike
Object:subscribe, the same callback may be registered
multiple times.
local Object = require('Object')
local myobject = Object()
local subscription = myobject:once('myevent', function()
print('hello world')
end)
myobject:publish('myevent') -- hello world
myobject:publish('myevent') -- nilThis repo also contains a Class.lua helper, which is simply a light wrapper
that allows calling user-defined classes directly to instantiate a corresponding
Object. Note that this requires overriding the metatable for the class:
local Class = require('Class')
local MyClass = Class()
function MyClass:_init(a, b)
self.sum = a + b
end
-- equivalent to Object(MyClass, 1, 2)
local myobject = MyClass(1, 2)You can also pass the class definition directly to Class:
local Class = require('Class')
local MyClass = Class({
_init = function(self, a, b)
self.sum = a + b
end
})