- Objects can have fields of any value (strings, other Object values, functions...).
- Object fields are, as for tables, always accessible and public.
- Field deletion is done by assigning a
nil
value. - Field access is done with ' . ', or ' : ' for methods, or '[ ]'
- An object has a type of
"Object"
- By convention, Luart use capital letters for objects definitions
Object oriented programming with Luart
Luart supports a wide range of object-oriented programming (OOP) concepts out of the box, including multilevel inheritance, polymorphism, encapsulation, etc.
Object
Objects are at the heart of OOP with Luart. Objects are specialized tables, made up of fields and methods. The difference with a Lua table is that an object makes it possible to create (or rather "instantiate") a value (called "instance") from this object, i.e. made up of the same fields and methods.
Objects are created using the global function Object().
Instantiation
Instantiation is the process of creating a value from an object. An object thus acts as a type, defining the capabilities of the value from its fields and methods.
Instantiation is simple with Luart : just call the previously defined object, which will return a new instance.
Constructor and destructor
Under the hood, the instantiation calls a specific object method to construct the instance called constructor
. When defined, the constructor
method of an object is used to initialize instances.
Conversely, when Lua destroys the instance (during a garbage collection cycle), the object's destructor
method, if defined, is called. This allows the instance to finalize/release resources before being destroyed.
Iterator
An iterator is an object method that is called when using an object instance in a for..in..
loop.
At each iteration, the iterator method is called with the self
value as first argument and an index
value as second argument. When starting the loop, the index value is nil
Once the iterator method has computed thewanted values, it should return them with the next index as the last return value. If the first returned value is nil
the loop ends. Otherwise, the iterator method is called once again with the new index, and so on...
Inheritance
Inheritance is the capability of one object ("the child") to derive or inherit the fields and methods from another object (called the "ancestor" or "parent").
With Luart, to define a child object that inherits from another parent object, you just need to use the parent object as an argument to the Object() global function.
Mixins
A mixin is a simple Lua table that can be mixed within an object to extend its capabilites. Mixins are like interfaces, but they also implements fields, methods, and properties to enrich an object.
Polymorphism
Polymorphism in programming refers to the use of the same field/method name across different types of objects.
Luart supports polymorphism between different objects and between inherited objects, by the possibility to redefine a field/a method at anytime.
Encapsulation
Object-oriented programming (OOP) relies heavily on encapsulation. All intrinsic data needed by the object to function correctly need to be hidden from the outside. This restriction prevents the accidental modification of data by preventing direct access to fields and methods. In this case, the data variables are referred to as private variables.
As tables in Lua, Luart does not provide true private fields for objects. But it's possible to achieve this by using the keyword local
for the needed variable outside the scope of the method or property where it is manipulated (see Visibility rules in Lua).
Properties
Properties are an important concept in OOP to support encapsulation. The term property refers to a special kind of object member, which falls between a field and a method in terms of functionality. The syntax for reading and writing properties is the same as that for fields, but the calls to the 'getter' and 'setter' methods translate properties into fields.
With Luart, properties are supported by the use of getter and setter methods for an object. The name of the getter method must start by the prefix get_
followed by the property name (for example, get_time
for the time
property. The name of the setter method must start by the prefix set_
followed by the property name (for example, set_time
for the time
property.