1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
local extends
--- Metatable used for each class created.
-- `__call` is an instance constructor.
-- `__index` and `_index` are used when accessing variables inside of class and its hierarchy when accessing class itself.
local metaclass do
local function _index (self, key)
local super = rawget(self, "__super")
if super then
local value = rawget(super, key)
if value ~= nil then
return value
end
return _index(super, key)
end
end
metaclass = {
__index = function (self, key)
if key == "extends" then
return extends
end
return _index(self, key)
end,
__call = function (self, ...)
local o = setmetatable({}, self)
self.new(o, ...)
return o
end
}
end
--- Method for checking if instance is of selected class.
-- Usage: `instance:is(Object)`.
-- Also works with classes: `Object:is(Object)`.
local is do
local function _is (self, class)
if self then
if self == class then
return true
end
return _is(rawget(self, "__super"), class)
end
end
function is (self, class)
local mt = getmetatable(self)
if mt ~= metaclass then
return _is(mt, class)
end
return _is(self, class)
end
end
--- Indexing metamethod for instances.
local index do
local function _index (self, key)
if self then
local value = rawget(self, key)
if value ~= nil then
return value
end
return _index(rawget(self, "__super"), key)
end
end
function index (self, key)
return _index(getmetatable(self), key)
end
end
--- Class creation/extension function.
-- Class table is used as metatable for instance of that class. `Metaclass` table is used as metatable for classes.
function extends (parent)
local self = setmetatable({}, metaclass)
rawset(self, "__class", self)
rawset(self, "__index", index)
rawset(self, "__super", parent)
return self
end
--- Base class used as root for class hierarchy.
local Object = extends(nil)
rawset(Object, "new", function () end)
rawset(Object, "is", is)
return Object
|