mirror of
https://github.com/vrld/hump.git
synced 2024-10-15 09:04:18 +00:00
Rewrite class system
This commit is contained in:
parent
5b1b67b23e
commit
9f678bc0e2
91
class.lua
91
class.lua
@ -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})
|
||||||
|
Loading…
Reference in New Issue
Block a user