Skip to content

Commit

Permalink
Rewrite class system
Browse files Browse the repository at this point in the history
  • Loading branch information
vrld committed Feb 20, 2013
1 parent 5b1b67b commit 9f678bc
Showing 1 changed file with 40 additions and 49 deletions.
89 changes: 40 additions & 49 deletions class.lua
Original file line number Diff line number Diff line change
Expand Up @@ -24,70 +24,61 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
]]--

local function __NULL__() end

-- class "inheritance" by copying functions
local function inherit(class, interface, ...)
if not interface then return end
assert(type(interface) == "table", "Can only inherit from other classes.")
local function include_helper(to, from, seen)
if type(from) ~= 'table' then
return from
elseif seen[from] then
return seen[from]
end

-- __index and construct are not overwritten as for them class[name] is defined
for name, func in pairs(interface) do
if not class[name] then
class[name] = func
seen[from] = to
for k,v in pairs(from) do
k = include_helper({}, k, seen) -- keys might also be tables
if not to[k] then
to[k] = include_helper({}, v, seen)
end
end
for super in pairs(interface.__is_a or {}) do
class.__is_a[super] = true
end
return to
end

return inherit(class, ...)
-- deeply copies `other' into `class'. keys in `other' that are already
-- defined in `class' are omitted
local function include(class, other)
return include_helper(class, other, {})
end

-- class builder
local function new(args)
local super = {}
local name = '<unnamed class>'
local constructor = args or __NULL__
if type(args) == "table" then
-- nasty hack to check if args.inherits is a table of classes or a class or nil
super = (args.inherits or {}).__is_a and {args.inherits} or args.inherits or {}
name = args.name or name
constructor = args[1] or __NULL__
end
assert(type(constructor) == "function", 'constructor has to be nil or a function')
-- returns a deep copy of `other'
local function clone(other)
return include({}, other)
end

-- build class
local class = {}
local function new(class)
class.__index = class
class.__tostring = function() return ("<instance of %s>"):format(tostring(class)) end
class.construct = constructor or __NULL__
class.inherit = inherit
class.__is_a = {[class] = true}
class.is_a = function(self, other) return not not self.__is_a[other] end
class.init = class.init or function() end
class.include = class.include or include
class.clone = class.clone or clone

-- inherit superclasses (see above)
inherit(class, unpack(super))
-- mixins
local inc = class.__includes or {}
if getmetatable(inc) then inc = {inc} end

for _, other in pairs(inc) do
include(class, other)
end

-- syntactic sugar
local meta = {
__call = function(self, ...)
local obj = {}
setmetatable(obj, self)
self.construct(obj, ...)
return obj
end,
__tostring = function() return name end
}
return setmetatable(class, meta)
-- constructor call
return setmetatable(class, {__call = function(c, ...)
local o = setmetatable({}, c)
o:init(...)
return o
end})
end

-- interface for cross class-system compatibility (see https://github.com/bartbes/Class-Commons).
if class_commons ~= false and not common then
common = {}
function common.class(name, prototype, parent)
local init = prototype.init or (parent or {}).init
return new{name = name, inherits = {prototype, parent}, init}
return include(new(prototype), parent)
end
function common.instance(class, ...)
return class(...)
Expand All @@ -96,5 +87,5 @@ end


-- the module
return setmetatable({new = new, inherit = inherit},
return setmetatable({new = new, include = include, clone = clone},
{__call = function(_,...) return new(...) end})

0 comments on commit 9f678bc

Please sign in to comment.