mirror of
https://github.com/kikito/middleclass.git
synced 2024-11-25 02:44:20 +00:00
109 lines
3.8 KiB
Lua
109 lines
3.8 KiB
Lua
|
-----------------------------------------------------------------------------------
|
|||
|
-- MiddleClass.lua
|
|||
|
-- Enrique Garc<72>a ( enrique.garcia.cota [AT] gmail [DOT] com ) - 19 Oct 2009
|
|||
|
-- Based on YaciCode, from Julien Patte and LuaObject, from S<>bastien Rocca-Serra
|
|||
|
-----------------------------------------------------------------------------------
|
|||
|
|
|||
|
do
|
|||
|
|
|||
|
-- returns a copy of table t (shallow copy: only level 1 is copied, non-recursive)
|
|||
|
local function duplicate(origin, destination, keys)
|
|||
|
-- no keys provided - duplicate all keys
|
|||
|
if keys==nil then for key,value in pairs(origin) do destination[key] = value end
|
|||
|
else for _,key in pairs(keys) do destination[key] = origin[key] end
|
|||
|
end
|
|||
|
return destination
|
|||
|
end
|
|||
|
|
|||
|
-----------------------------------------------------------------------------------
|
|||
|
-- The 'Object' class
|
|||
|
Object = {
|
|||
|
name = "Object",
|
|||
|
superClass = nil,
|
|||
|
subClassOf = function(class, other) return false end, -- Object inherits from nothing
|
|||
|
|
|||
|
made = function(class, obj)
|
|||
|
if type(obj)~="table" or type(obj.class)~="table" then return false end
|
|||
|
local c = obj.class
|
|||
|
if c==class then return true end
|
|||
|
if type(c)~="table" or type(c.subClassOf)~="function" then return false end
|
|||
|
return c:subClassOf(class)
|
|||
|
end,
|
|||
|
|
|||
|
new = function (class, ...)
|
|||
|
local instance = setmetatable({ class = class }, { __index = class.instanceMethods })
|
|||
|
instance:init(...)
|
|||
|
return instance
|
|||
|
end,
|
|||
|
|
|||
|
subClass = function(baseClass, name)
|
|||
|
if type(name)~="string" then name = "Unnamed" end
|
|||
|
|
|||
|
local theClass = {
|
|||
|
name = name,
|
|||
|
superClass = baseClass,
|
|||
|
subClassOf = function (class, other) return (baseClass==other or baseClass:subClassOf(other)) end,
|
|||
|
instanceMethods = {}
|
|||
|
}
|
|||
|
|
|||
|
duplicate(baseClass, theClass, {'includes', 'new', 'made', 'subClass'})
|
|||
|
|
|||
|
duplicate(baseClass.instanceMethods, theClass.instanceMethods, {
|
|||
|
'__add', '__call', '__concat', '__div', '__eq', '__le', '__len', '__lt',
|
|||
|
'__mod', '__mul', '__pow', '__sub', '__tostring', '__unm'
|
|||
|
})
|
|||
|
|
|||
|
setmetatable(theClass.instanceMethods, {__index = baseClass}) -- if a method is not found on instanceMethods, look on baseClass
|
|||
|
|
|||
|
setmetatable(theClass, {
|
|||
|
__index = theClass.instanceMethods, -- if a method is not found, look on "instanceMethods"
|
|||
|
__newindex = function(class, methodName, method) -- add new items to the "instanceMethods" attribute, building "super" at the same time
|
|||
|
if type(method) == 'function' then
|
|||
|
local superMethod = function(self, ...) return baseClass.instanceMethods[methodName](self, ...) end
|
|||
|
local fenv = getfenv(method)
|
|||
|
local newEnv = setmetatable( { super = superMethod }, {__index = fenv, __newindex = fenv} )
|
|||
|
setfenv( method, newEnv )
|
|||
|
end
|
|||
|
rawset(class.instanceMethods, methodName, method)
|
|||
|
end,
|
|||
|
__tostring = function() return ("class ".. name) end,
|
|||
|
__call = newInstance
|
|||
|
})
|
|||
|
|
|||
|
theClass.instanceMethods.init = function (instance,...) super(self) end
|
|||
|
|
|||
|
return theClass
|
|||
|
end,
|
|||
|
|
|||
|
-- Extension function - similar to ruby's include for modules
|
|||
|
-- adds the methods of t to the class
|
|||
|
-- will invoke the included method if present
|
|||
|
includes = function(self, t)
|
|||
|
duplicate(t, self)
|
|||
|
if t.included~=nil then t:included(self) end
|
|||
|
end
|
|||
|
}
|
|||
|
|
|||
|
Object.instanceMethods = {
|
|||
|
init = function(instance, ...) end
|
|||
|
}
|
|||
|
|
|||
|
setmetatable(Object.instanceMethods, {
|
|||
|
__tostring = function (instance) return ("a ".. instance.class.name) end
|
|||
|
})
|
|||
|
|
|||
|
setmetatable(Object, {
|
|||
|
__tostring = function() return ("class Object") end,
|
|||
|
__call = newInstance
|
|||
|
})
|
|||
|
|
|||
|
----------------------------------------------------------------------
|
|||
|
-- function 'class'
|
|||
|
function class(name, baseClass)
|
|||
|
baseClass = baseClass or Object
|
|||
|
return baseClass:subClass(name)
|
|||
|
end
|
|||
|
|
|||
|
end
|
|||
|
-- end of code
|