Concepts
Class and Instances
A class is a xtype's type with fields to define behavior for its instances.
It has the xtype_*
and __meta
(when built) special fields.
An instance is a table with behavior defined by a specific class.
Type and Inheritance
Type checking and order of inheritance are already specified by xtype.
A class inherits from its base classes fields, except for the xtype_*
and
__meta
fields.
An instance inherits from its class fields (with inheritance), except for
xtype_*
and those starting with __
, which are special class fields.
Inheritance of fields is not dynamic (cached for performance) and is built by
class.build
, which must be called for any later changes to the class
definition or base classes.
The build of a class is independent of other class builds and will affect all its instances. The class is also partially built from the base classes when created (i.e. the class inheritance, not the instance inheritance).
class.build
is already called when using a class for instantiation for the
first time; in most cases calling this function is unnecessary because the class
is completely defined when used.
Special Methods
Special methods are prefixed by __
.
Misc:
method | description |
---|---|
construct | called at initialization |
destruct | called at garbage collection |
Warning: With Lua 5.1 or LuaJIT, neither the table __gc
metamethod or
ephemeron tables are implemented, thus a __proxy_gc
field will be added to
instances of a class with a destructor.
Unary operators:
method | description |
---|---|
call | like the metamethod |
tostring | like the metamethod |
unm | like the metamethod |
len | like the metamethod |
bnot | like the metamethod |
Binary Operators
xtype op multifunctions are assigned to the corresponding metamethods in the instance metatable.
Private / Protected
There is no private/protected mechanism implemented.
"Private" methods can be achieved with local functions in the class definition.
local function pmethod(self)
end
"Private" instance data can be achieved using a local table in the class definition with weak keys for the instances.
local privates = setmetatable({}, {__mode = "k"})
function Object:__construct()
privates[self] = { a = 1, b = 2 }
end
function Object:method()
local p = privates[self]
p.a = p.a*p.b
end
API
-- Create a new class.
-- Base types can be classes or other xtypes.
--
-- name: human-readable string (doesn't have to be unique)
-- ...: base types, ordered by descending proximity, to the least specific type
-- return created class (an xtype)
class.new(name, ...)
-- ALIAS class(name, ...)
-- Create instance.
-- Will build the class if not already built.
--
-- classdef: class
-- ...: constructor arguments
-- return created instance
class.instantiate(classdef, ...)
-- ALIAS Class(...)
-- Build/re-build the class (class and instance inheritance).
-- Will add the `__meta` field to the class.
--
-- classdef: class
class.build(classdef)
-- Get the class metatable applied to the instances.
-- Will build the class if not already built; useful to apply class behaviour
-- to a custom table.
--
-- classdef: class
-- return metatable
class.meta(classdef)
Examples
Type Checking
A = class("A")
a = A()
xtype.is(A, class) -- true
xtype.is(a, A) -- true
Multiple Inheritance and Override
A = class("A")
function A:test() print("a") end
B = class("B")
function B:test() print("b") end
C = class("C", A, B) -- inheritance from A and B
function C:test() -- force the usage of B:test()
B.test(self)
end
Constructor Override
A = class("A")
function A:__construct() print("A") end
B = class("B", A)
function B:__construct()
A.__construct(self) -- call parent A constructor
print("B")
end
Binary Operator Definition
vec2 = class("vec2")
function vec2:__construct(x, y) self.x, self.y = x, y end
xtype.op.add:define(function(a, b)
return vec2(a.x+b.x, a.y+b.y)
end, vec2, vec2)