summaryrefslogtreecommitdiff
path: root/Object.lua
blob: 9b9080b5eb7a74c6ccd9f28d55dd8ca919bb76a5 (plain)
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