MiddleClass: fixed nonworking implicit instantiation (Object() instead of Object:new())

This commit is contained in:
kikito 2010-02-13 17:32:37 +00:00
parent b9248f5cc1
commit df05036c61

View File

@ -7,69 +7,69 @@
local classes = setmetatable({}, {__mode = "k"}) -- weak table storing references to all declared classes local classes = setmetatable({}, {__mode = "k"}) -- weak table storing references to all declared classes
-- The 'Object' class -- The 'Object' class
Object = { name = "Object", Object = { name = "Object" }
-- creates a new instance -- creates a new instance
new = function(class, ...) Object.new = function(class, ...)
assert(classes[class]~=nil, "Use class:new instead of class.new") assert(classes[class]~=nil, "Use class:new instead of class.new")
local instance = setmetatable({ class = class }, class.__classDict) -- the class dictionary is the instance's metatable local instance = setmetatable({ class = class }, class.__classDict) -- the class dictionary is the instance's metatable
instance:initialize(...) instance:initialize(...)
return instance return instance
end, end
-- creates a subclass -- creates a subclass
subclass = function(superclass, name) Object.subclass = function(superclass, name)
assert(classes[superclass]~=nil, "Use class:subclass instead of class.subclass") assert(classes[superclass]~=nil, "Use class:subclass instead of class.subclass")
if type(name)~="string" then name = "Unnamed" end if type(name)~="string" then name = "Unnamed" end
local theClass = { name = name, superclass = superclass, __classDict = {} } local theClass = { name = name, superclass = superclass, __classDict = {} }
local classDict = theClass.__classDict local classDict = theClass.__classDict
-- This one is weird. Since: -- This one is weird. Since:
-- a) the class dict is the instances' metatable (so it must have an __index for looking up the methods) and -- a) the class dict is the instances' metatable (so it must have an __index for looking up the methods) and
-- b) The instance methods are in the class dict itself, then ... -- b) The instance methods are in the class dict itself, then ...
classDict.__index = classDict classDict.__index = classDict
-- if a method isn't found on the class dict, look on its super class -- if a method isn't found on the class dict, look on its super class
setmetatable(classDict, {__index = superclass.__classDict} ) setmetatable(classDict, {__index = superclass.__classDict} )
-- theClass also needs some metamethods -- theClass also needs some metamethods
setmetatable(theClass, { setmetatable(theClass, {
__index = function(_,methodName) __index = function(_,methodName)
local localMethod = classDict[methodName] -- this allows using classDic as a class method AND instance method dict local localMethod = classDict[methodName] -- this allows using classDic as a class method AND instance method dict
if localMethod ~= nil then return localMethod end if localMethod ~= nil then return localMethod end
return superclass[methodName] return superclass[methodName]
end, end,
-- FIXME add support for __index method here -- FIXME add support for __index method here
__newindex = function(_, methodName, method) -- when adding new methods, include a "super" function __newindex = function(_, methodName, method) -- when adding new methods, include a "super" function
if type(method) == 'function' then if type(method) == 'function' then
local fenv = getfenv(method) local fenv = getfenv(method)
local newenv = setmetatable( {super = superclass.__classDict}, {__index = fenv, __newindex = fenv} ) local newenv = setmetatable( {super = superclass.__classDict}, {__index = fenv, __newindex = fenv} )
setfenv( method, newenv ) setfenv( method, newenv )
end end
rawset(classDict, methodName, method) rawset(classDict, methodName, method)
end, end,
__tostring = function() return ("class ".. name) end, __tostring = function() return ("class ".. name) end,
__call = theClass.new __call = Object.new
}) })
-- instance methods go after the setmetatable, so we can use "super" -- instance methods go after the setmetatable, so we can use "super"
theClass.initialize = function(instance,...) super.initialize(instance) end theClass.initialize = function(instance,...) super.initialize(instance) end
classes[theClass]=theClass --registers the new class on the list of classes classes[theClass]=theClass --registers the new class on the list of classes
return theClass return theClass
end, end
-- Mixin extension function - simulates very basically ruby's include(module) -- Mixin extension function - simulates very basically ruby's include(module)
-- module is a lua table of functions. The functions will be copied to the class -- module is a lua table of functions. The functions will be copied to the class
-- if present in the module, the included() method will be called -- if present in the module, the included() method will be called
includes = function(class, module) Object.includes = function(class, module)
assert(classes[class]~=nil, "Use class:includes instead of class.includes") assert(classes[class]~=nil, "Use class:includes instead of class.includes")
for methodName,method in pairs(module) do for methodName,method in pairs(module) do
if methodName ~="included" then class[methodName] = method end if methodName ~="included" then class[methodName] = method end
end
if type(module.included)=="function" then module:included(class) end
end end
if type(module.included)=="function" then module:included(class) end
end
}
classes[Object]=Object -- adds Object to the list of classes classes[Object]=Object -- adds Object to the list of classes