-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathclass.lua
More file actions
80 lines (67 loc) · 2.57 KB
/
class.lua
File metadata and controls
80 lines (67 loc) · 2.57 KB
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
local table = require 'ext.table'
-- classes
local function newmember(class, ...)
local obj = setmetatable({}, class)
if obj.init then return obj, obj:init(...) end
return obj
end
local classmeta = {
__call = function(self, ...)
-- [[ normally:
return self:new(...)
--]]
--[[ if you want to keep track of all instances
local results = table.pack(self:new(...))
local obj = results[1]
self.instances[obj] = true
return results:unpack()
--]]
end,
}
-- usage: class:isa(obj)
-- so it's not really a member method, since the object doesn't come first, but this way we can use it as Class:isa(obj) and not worry about nils or local closures
local function isa(cl, obj)
assert(cl, "isa: argument 1 is nil, should be the class object") -- isa(nil, anything) errors, because it should always have a class in the 1st arg
if type(obj) ~= 'table' then return false end -- class:isa(not a table) will return false
-- Check the metatable for an .isaSet first
-- This allows the object the ability to lose the 'isa' and 'isaSet' fields.
-- It also allows isa(class, subclass) to work.
local mt = getmetatable(obj)
local isaSet = mt and mt.isaSet or obj.isaSet
if not isaSet then return false end -- not an object generated by class(), so it doesn't have a set of all classes that it "is-a"
return isaSet[cl] or false -- returns true if the 'isaSet' of the object's metatable (its class) holds the calling class
end
local function class(...)
local cl = table(...)
-- TODO maybe, get rid of this and just use getmetatable()
cl.class = cl
cl.super = ... -- .super only stores the first. the rest can be accessed by iterating .isaSet's keys
-- I was thinking of calling this '.superSet', but it is used for 'isa' which is true for its own class, so this is 'isaSet'
cl.isaSet = {[cl] = true}
for i=1,select('#', ...) do
local parent = select(i, ...)
if parent ~= nil then
cl.isaSet[parent] = true
if parent.isaSet then
for grandparent,_ in pairs(parent.isaSet) do
cl.isaSet[grandparent] = true
end
end
end
end
-- store 'descendantSet' as well that gets appended when we call class() on this obj?
for ancestor,_ in pairs(cl.isaSet) do
ancestor.descendantSet = ancestor.descendantSet or {}
ancestor.descendantSet[cl] = true
end
cl.__index = cl
cl.new = newmember
cl.isa = isa -- usage: Class:isa(obj)
cl.subclass = class -- such that cl:subclass() or cl:subclass{...} will return a subclass of 'cl'
--[[ if you want to keep track of all instances
cl.instances = setmetatable({}, {__mode = 'k'})
--]]
setmetatable(cl, classmeta)
return cl
end
return class