LiquidProxy Lua Edition
at master 73 lines 2.3 kB view raw
1local table = require 'ext.table' 2 3-- classes 4 5local function newmember(class, ...) 6 local obj = setmetatable({}, class) 7 if obj.init then return obj, obj:init(...) end 8 return obj 9end 10 11local classmeta = { 12 __call = function(self, ...) 13-- [[ normally: 14 return self:new(...) 15--]] 16--[[ if you want to keep track of all instances 17 local results = table.pack(self:new(...)) 18 local obj = results[1] 19 self.instances[obj] = true 20 return results:unpack() 21--]] 22 end, 23} 24 25-- usage: class:isa(obj) 26-- 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 27local function isa(cl, obj) 28 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 29 if type(obj) ~= 'table' then return false end -- class:isa(not a table) will return false 30 if not obj.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" 31 return obj.isaSet[cl] or false -- returns true if the 'isaSet' of the object's metatable (its class) holds the calling class 32end 33 34local function class(...) 35 local cl = table(...) 36 cl.class = cl 37 38 cl.super = ... -- .super only stores the first. the rest can be accessed by iterating .isaSet's keys 39 40 -- I was thinking of calling this '.superSet', but it is used for 'isa' which is true for its own class, so this is 'isaSet' 41 cl.isaSet = {[cl] = true} 42 for i=1,select('#', ...) do 43 local parent = select(i, ...) 44 if parent ~= nil then 45 cl.isaSet[parent] = true 46 if parent.isaSet then 47 for grandparent,_ in pairs(parent.isaSet) do 48 cl.isaSet[grandparent] = true 49 end 50 end 51 end 52 end 53 54 -- store 'descendantSet' as well that gets appended when we call class() on this obj? 55 for ancestor,_ in pairs(cl.isaSet) do 56 ancestor.descendantSet = ancestor.descendantSet or {} 57 ancestor.descendantSet[cl] = true 58 end 59 60 cl.__index = cl 61 cl.new = newmember 62 cl.isa = isa -- usage: Class:isa(obj) 63 cl.subclass = class -- such that cl:subclass() or cl:subclass{...} will return a subclass of 'cl' 64 65--[[ if you want to keep track of all instances 66 cl.instances = setmetatable({}, {__mode = 'k'}) 67--]] 68 69 setmetatable(cl, classmeta) 70 return cl 71end 72 73return class