esi-class
Base class for object oriented programming in lua This library shall be used for each library where object orientation makes sense.
Basic Concept
This library incorportes different concepts required for object oriented Programming, while still keeping memory foodprint and performance in mind.
Inheritance
Inheritance is currently limited to simple direct inheritance, there is currently no possibility to inherit from more than one class. Creating a new class is done by calling the "__EXTEND__" methode on a CLASS. This methods requires a name and may take a property template (the class declaration). But it is also possible to add class members after the definition of the class itself.
Example
-- create an new class, whith only class varaibles and default __INIT__ function
local ESI_CLASS = require("esi-class")
local myClass = ESI_CLASS:__EXTEND__("myClass", {
propertyA = "a", -- class varibale
propertyB = "b" -- class variable
})
function myClass:GET_A()
return self.propertyA
end
function myClass:GET_B()
return self.propertyB
end
local instance1 = myClass() -- create an instance
local instance2 = myClass() -- create an instance
local a1 = instance1:GET_A()
local a2 = instance2:GET_A()
local b1 = instance1:GET_B()
local b2 = instance2:GET_B()
local aClass = myClass:GET_A()
local bClass = myClass:GET_B()
return {aClass= aClass, bClass= bClass, a1=a1,a2=a2, b1=b1, b2=b2 }
Example
-- create an new class, whith it's own init funtion
local ESI_CLASS = require("esi-class")
local SUBTYPE = require("esi-subtype")
local TOOL = require("esi-tool")
local myClass = ESI_CLASS:__EXTEND__("myClass", {
__INIT__ = function(class, template)
-- copy constructor
if SUBTYPE.get(template) == class:__GET_CLASSNAME__() then
return TOOL:DEEPCOPY(template, 0)
else
-- regular constructor
-- declaration ( with default value )
local obj = {
a = "unknown",
b = "unknown"
}
-- initialization by template input.
obj.a= template.a or obj.a
obj.b= template.a or obj.b
return obj
end
end
})
function myClass:GET_A()
return self.a
end
function myClass:GET_B()
return self.b
end
-- create some instances of myClass
local instance1 = myClass({a=1, b=2}) -- create an 1st instance
local instance2 = myClass({a=3, b=4}) -- create an 2nd instance
local instance3 = myClass(instance1) -- copy constructor
return { instance1, instance2, instance3 }
Objects
Object are created by calling the CLASS object. Internally this first calls the "__INIT__" methode and then the "__SET_CLASS__ methode. As "__SET_CLASS__" should be suitable for most classe, only the "__INIT__" methode has to be defined for a new class. The name ase well as the behaviour are inspired by python, and should be used in a similar way.
HINT: Don’t define function or any other lua object, which is not JSON serializable in the object which is returned by the __INIT__ function. Functions shall always be defined as a property of the class ( either as input to the __EXTEND__ method or defined later).
Underlying Architecture: The idea of this whole inheritance is, that each object is a LuaTable on it’s own rights. All class specific content like "__className", "__parent" and all functions on can call on this object are in the metatable. This is achieved, by assigning the class of an object to the __index entry. So the __index of each object points to it’s class and thus allows to access everything which was defined on that class. But the class is a object on it’s own rights as well, which also has an metatable and also has an __index entry, but this points to the parent class. That way inheritance is realised, by following the chain of __index calls automatically done by lua. In oder to create (inherit) a new class the __EXTEND__ function must be called on the base class. As part of this extention, an __INIT__ function should be defined for that class ( similar to python ), this function actually initializes the objects and defines all object specific data. The object defined in the __INIT__ function should be JSON serializable (no functions). In additiona to the __INIT__ function, a __SET_CLASS__ function exists, but this is inherited from esi-class automatically and should not be touched. ( exceptions exist ) If an new object is instanciated, the __INIT__ function of the class is called to create the LuaTable (content) which is not a "object" yet, and then the __SET_CLASS__ function is called to initialize all metatable related entries, which form the "object" character. That happens automatically behind the scenes by the __call function. ( this was added to the metatable of the newly created class by the __EXTEND__() function )
Dependencies
library | version | inmation core library |
---|---|---|
debug |
1.0.0 |
yes |
rapidjson |
0.6.0 |
yes |
esi-tool |
1.0.0 |
yes |
esi-subtype |
1.0.0 |
yes |
Available functions
All functions have to be called according to the ESI standard, using colons, e.g. lib:FUNCTIONNAME(params)
Documentation
_LOG_ERROR(topic,detail)
Log error message
creates an error entry via syslib.log if logging is enabled by SET_LOG(true).
Usage
local esi_lib = require "esi-class"
local myClass = esi_lib:__EXTEND__("myClass")
local object = myClass()
object:SET_LOG(true)
object:_LOG_ERROR("Current Area", "Something went wrong ...") -- with traceback
object:_LOG_ERROR("Current Area", "Something went wrong ...", false) -- without traceback
_LOG_WARN(topic,detail) \{#LOG_WARN}
Log warn message
creates an warn entry via syslib.log if logging is enabled by SET_LOG(true).
_LOG_INFO(topic,detail)
Log info message
creates an info entry via syslib.log if logging is enabled by SET_LOG(true).
_LOG_DEBUG(topic,detail)
Log debug messages
creates an debug entry via syslib.log if logging is enabled by SET_LOG(true) and debug is enabled via SET_DEBUG(true).
_ASSERT(condition,error_message)
ASSERT
this is an local assert function, calls a assert if debugging was enabled via SET_DEBUG(true). otherwise it only checks the assertion and creates an error entry if the assertion is false.
__SET_CLASS__(class)
Set the class related properties if the object (self)
only used during construction of objects
__SUPER__()
Get the super class
get the super class of a class. to get the super class of an object you have to call GET_CLASS() first.