summaryrefslogtreecommitdiffhomepage
path: root/lib/Object.lua
blob: b241bb26d1fcab781c3304553acdaeea73dce8f0 (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
--- You may not believe me but we are not returning this one.
-- This table is used as metatable for classes e.g. for `Object`.
local Class = {}

--- Metamethod for classes.
-- Creates new instance of class calling `new()` method (constructor) with all parameters passed.
Class.__call = function (self, ...)
	local o = setmetatable({}, self)
	self.new(o, ...)
	return o
end

--- Metamethod for classes.
-- First checks if `__index` (instance prototype) have field we are looking for. Then it tries to find it in super class.
Class.__index = function (self, key)
	if rawget(self, "__index") ~= nil then
		if rawget(self, "__index")[key] ~= nil then
			return rawget(self, "__index")[key]
		end
	end
	if rawget(self, "__super") ~= nil then
		if rawget(self, "__super")[key] ~= nil then
			return rawget(self, "__super")[key]
		end
	end
	return nil
end
--- Metamethod for classes.
-- Redirects creating new properties to class'es `__index` which is used as a prototype for instances of class.
-- Only `new` method and metamethods are allowed to be written to class'es table directly.
Class.__newindex = function(self, key, value)
	if key == "new" or key:sub(1, 2) == "__" then
		rawset(self, key, value)
	else
		self.__index[key] = value
	end
end

--- Creates new class from parent class.
-- New class will call parent's constructor unless new constructor will be defined.
-- @param parent super class of new class
local extends = function (parent)
	local self = setmetatable({}, Class)
	rawset(self, "__index", {})
	if parent then
		setmetatable(self.__index, {__index = parent.__index})
	end
	rawset(self, "__super", parent)
	return self
end

--- Almost empty class.
-- Used to create new classes via `extend()` method:
-- `Child = Object:extend()`
-- Contains `is()` and `new()` methods. Later one isn't available from inside of instances.
local Object = extends(nil)
rawset(Object, "extends", extends)
Object.new = function (self) end

--- Checks if class or instance of class is a child of class passed through parameter.
-- @param class table we want to test against (preferably class table)
-- @return boolean which is false if tested sample is not child of passed class
function Object:is (class)
	if not class then return false end
	if self == class or getmetatable(self) == class then
		return true
	end
	if self.__super then
		return self.__super:is(class)
	end
	if getmetatable(self).__super then
		return getmetatable(self).__super:is(class)
	end
	return false
end

return Object