esi-class

Base class for object oriented programming in Lua

This library should be used for each library where object orientation makes sense.

Basic Concept

This library incorporates different concepts required for object oriented programming, while keeping memory footprint and performance in mind.

Inheritance

Inheritance is currently limited to simple direct inheritance. Currently there is no possibility to inherit from more than one class. Creating a new class is done by calling the "__EXTEND__" method 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 a new class, with only class variables 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 a new class, with its own init function
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
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__" method and then the "__SET_CLASS__" method. As "__SET_CLASS__" should be suitable for most classes, only the "__INIT__" method has to be defined for a new class. The name as well as the behavior are inspired by python, and should be used in a similar way. See: https://docs.python.org/3/tutorial/classes.html#a-first-look-at-classes

Object Hint

Don’t define a 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 in its own right. All class specific content like "__className", "__parent" and all functions which can be called on this object are in the metatable. This is archived by assigning the class of an object to the __index entry. So the __index of each object points to its class and thus allows to access everything which was defined in that class. But the class is an object on its own right as well, which also has a metatable and also has an __index entry, but this points to the parent class.

Inheritance

That way inheritance is realized, 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 extension, 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 addition 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 a new object is instantiated, the __INIT__ function of the class is called to create the LuaTable (content) which is not an "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

Documentation

CLASS:VERSION

Description

VERSION returns the version of the library / class

Returns

returns the version of the library / class

Examples

local version = CLASS:VERSION()

CLASS:MODULE

Description

MODULE returns the modulename of the library / class

Returns

returns the modulename of the library / class

Examples

local version = CLASS:MODULE()

CLASS:SET_DEBUG

Description

SET_DEBUG sets or resets the _debug flag

Parameters

Name Description

on

set to on, when true

Returns

sets or resets the _debug flag

Examples

local version = CLASS:SET_DEBUG(true)

CLASS:SET_LOG

Description

SET_LOG sets or resets the _log flag

Parameters

Name Description

on

set to on, when true

Returns

sets or resets the _log flag

Examples

local version = CLASS:SET_LOG(true)

CLASS:_LOG_ERROR

Description

Log error message

creates an error entry via syslib.log if logging is enabled by SET_LOG(true).

Parameters

Name Description

topic

the current scope / topic

detail

details for the log message

traceOn

if true or nil, enables the traceback in the error message.

Returns

returns nothing

Examples

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

CLASS:_LOG_WARN

Description

Log warn message

creates an warn entry via syslib.log if logging is enabled by SE_LOG(true).

Parameters

Name Description

topic

the current scope / topic

detail

details for the log message

Returns

returns nothing, but creates log entry.

Examples

object:_LOG_WARN("Current Area", "Warning: something is wrong ...")

CLASS:_LOG_INFO

Description

Log info message

creates an info entry via syslib.log if logging is enabled by SET_LOG(true).

Parameters

Name Description

topic

the current scope / topic

detail

details for the log essage

Returns

returns nothing, but creates log entry.

Examples

object:_LOG_INFO("Current Area", "Info: created an info")

CLASS:_LOG_DEBUG

Description

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).

Parameters

Name Description

topic

the current scope / topic

detail

details for the log essage

Returns

returns nothing

Examples

object:_LOG_DEBUG("Current Area", "Debug: started activity ...")

CLASS:_ASSERT

Description

ASSERT

this is a local assert function, calls an assert if debugging was enabled via SET_DEBUG(true).
due to limitations in Lua, this does not work exactly like calling assert() in the code, but similar.
here traceback is used to generate useful information in the assert message.
otherwise it only checks the assertion and creates an error entry if the assertion is false.

Parameters

Name Description

condition

value or condition which is evaluated

error_message

message shown if condition is false

Returns

nothing

Examples

object:_ASSERT(false, "this is never true")

CLASS:__INIT__

Description

Init an object prior to assigning the class

default initialization, table like.
only used during construction of objects

Parameters

Name Description

initObj

static initialization object

Returns

initializes object

CLASS:__SET_CLASS__

Description

Set the class related properties if the object (self)

only used during construction of objects

Parameters

Name Description

class

the class the object shall belong to.

Returns

object with metatable entries

CLASS:__GET_CLASS__

Description

Get Class object of a member object

Returns

class object linked to an object.

CLASS:__SUPER__

Description

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.

Returns

super class

CLASS:__EXTEND__

Description

Extend an existing class definitions

this should be called on a CLASS object, or inherited from a class.

Parameters

Name Description

name

name of the new class

classProperties

Returns

new class of type <name>

Examples

local newClass = CLASS:__EXTEND__("MyNewClass", {NewProperty1= 1})

CLASS:__GET_CLASSNAME__

Description

Get classname of an object or a class

Returns

Classname or ""

Examples

CLASS:__GET_CLASSNAME__()