Rewrite class system

This commit is contained in:
Matthias Richter 2013-02-20 15:53:13 +01:00
parent 5b1b67b23e
commit 9f678bc0e2

View File

@ -24,70 +24,61 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
]]-- ]]--
local function __NULL__() end local function include_helper(to, from, seen)
if type(from) ~= 'table' then
return from
elseif seen[from] then
return seen[from]
end
-- class "inheritance" by copying functions seen[from] = to
local function inherit(class, interface, ...) for k,v in pairs(from) do
if not interface then return end k = include_helper({}, k, seen) -- keys might also be tables
assert(type(interface) == "table", "Can only inherit from other classes.") if not to[k] then
to[k] = include_helper({}, v, seen)
-- __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
end end
end end
for super in pairs(interface.__is_a or {}) do return to
class.__is_a[super] = true
end
return inherit(class, ...)
end end
-- class builder -- deeply copies `other' into `class'. keys in `other' that are already
local function new(args) -- defined in `class' are omitted
local super = {} local function include(class, other)
local name = '<unnamed class>' return include_helper(class, other, {})
local constructor = args or __NULL__ end
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')
-- build class -- returns a deep copy of `other'
local class = {} local function clone(other)
return include({}, other)
end
local function new(class)
class.__index = class class.__index = class
class.__tostring = function() return ("<instance of %s>"):format(tostring(class)) end class.init = class.init or function() end
class.construct = constructor or __NULL__ class.include = class.include or include
class.inherit = inherit class.clone = class.clone or clone
class.__is_a = {[class] = true}
class.is_a = function(self, other) return not not self.__is_a[other] end
-- inherit superclasses (see above) -- mixins
inherit(class, unpack(super)) local inc = class.__includes or {}
if getmetatable(inc) then inc = {inc} end
-- syntactic sugar for _, other in pairs(inc) do
local meta = { include(class, other)
__call = function(self, ...) end
local obj = {}
setmetatable(obj, self) -- constructor call
self.construct(obj, ...) return setmetatable(class, {__call = function(c, ...)
return obj local o = setmetatable({}, c)
end, o:init(...)
__tostring = function() return name end return o
} end})
return setmetatable(class, meta)
end end
-- interface for cross class-system compatibility (see https://github.com/bartbes/Class-Commons). -- interface for cross class-system compatibility (see https://github.com/bartbes/Class-Commons).
if class_commons ~= false and not common then if class_commons ~= false and not common then
common = {} common = {}
function common.class(name, prototype, parent) function common.class(name, prototype, parent)
local init = prototype.init or (parent or {}).init return include(new(prototype), parent)
return new{name = name, inherits = {prototype, parent}, init}
end end
function common.instance(class, ...) function common.instance(class, ...)
return class(...) return class(...)
@ -96,5 +87,5 @@ end
-- the module -- the module
return setmetatable({new = new, inherit = inherit}, return setmetatable({new = new, include = include, clone = clone},
{__call = function(_,...) return new(...) end}) {__call = function(_,...) return new(...) end})