-
Notifications
You must be signed in to change notification settings - Fork 53
Instances
An instance can be created from any class using class:new()
:
local appWindow = Window:new()
30log provides a syntactic sugar for creating instances, for convenience.
local appWindow = Window() -- same as Window:new()
print(appWindow.width, appWindow.height) -- outputs 150, 100
An instance has a free access to its class attributes.
print(appWindow.width, appWindow.height) -- outputs 150, 100
An instance also has its own copy of those attributes.
Assigning them new values will only affect these copies.
appWindow.width, appWindow.height = 720, 480
print(appWindow.width, appWindow.height) -- outputs 720, 480
print(Window.width, Window.height) -- outputs 150, 100, hence class attributes are left
From the previous examples, one might have noticed that once an instance is created, it already shares the attributes of his class.
Yet, instances can be initialized in a custom manner. In this way, they will have custom attributes and values already set. To achieve this, a class constructor should be implemented. Typically, this is a method (a function) that will be called internally within class:new()
.
30log uses a reserved key, named init
for class constructors.
local Window = class("Window")
function Window:init(width, height)
self.width, self.height = width, height
end
local appWindow = Window(800,600)
print(appWindow.width, appWindow.height) -- output 800, 600
The class constructor init
can also be defined as a table with named keys, instead of a function. In that case, any new instance created will get a raw copy of the keys and values found in this table: this is called static instantiation.
local Window = class("Window")
Window.init = {width = 500, height = 500}
appWindow = Window()
print(appFrame.width, appFrame.height) -- outputs 500, 500
It is also possible to allocate a new instance via class:create()
. In this case though, the class constructor, even if defined, will not be invoked.
local appWindow = Window:create()
print(appWindow:instanceOf(Window)) -- outputs "true"
print(appWindow.width, appWindow.height) -- outputs nil, nil
Window.width = 250 -- Sets a default width for the class
print(appWindow.width) -- outputs 250
Instances from any class have a built-in method, named :instanceOf()
to inspect if a given instance originates from a specific class.
For example, we want to know if appWindow
is an instance from Window
class.
print(appWindow:instanceOf(Window)) -- outputs true
It also returns true even if the given class is not the direct class from which the instance originates, but rather, a superclass, as shown in the following example:
local GraphicalObject = class('GraphicalObject')
local Rect = GraphicalObject:extend('Rect')
local Window = Rect:extend('Window')
local appWindow = Window()
print(appWindow:instanceOf(Window)) -- outputs true
print(appWindow:instanceOf(Rect)) -- outputs true
print(appWindow:instanceOf(GraphicalObject)) -- outputs true
The class from which an instance originates can be changed via the cast()
method.
local Rect = class('Rect')
local Window = class('Window')
local w = Rect()
print(w:instanceOf(Rect)) -- outputs true
w:cast(Window) -- Sets class 'Window' to be the class of instance 'w'
print(w:instanceOf(Rect)) -- outputs false
print(w:instanceOf(Window)) -- outputs true
print(w.class) -- outputs class 'Window'
When a cast was made, the instance has no longer access to its previous class methods, but instead it uses its new class methods.
local Rect = class('Rect')
function Rect:init(width, height)
self.width, self.height = width, height
end
function Rect:area()
return self.width * self.height
end
local Window = class('Window')
function Window:init(width, height)
self.width, self.height = width, height
end
function Window:halve()
self.width, self.height = width / 2, height / 2
end
local w = Rect(10, 5)
print(w:area()) -- outputs 50
w:cast(Window)
w:area() -- raises an error
w:halve()
print(w.width, w.height) -- outputs 5, 2.5
As for classes, passing an instance to print or tostring returns a string representing the instance. This string specifies the passed-in object is an instance, gives its class name and the memory address of the instance.
local Window = class("Window")
local appWindow = Window()
print(appWindow) -- "instance of 'Window' (table: 0x0002cf70)"
local Window = class()
local appWindow = Window()
print(appWindow) -- "instance of '?' (table: 0x0002cf70)"
Also, instances have an attribute named class
which points to their class.
print(appWindow.class) -- "class 'Window' (table: 0x0002cdf8)"
30log classes are metatables of their own instances. This implies that one can inspect the relationship between a class and its instances using getmetatable.
local aClass = class()
local someInstance = aClass()
print(getmetatable(someInstance) == aClass) -- true