removed getterSetters from main MiddleClass (use a mixin instead). Added destroy. Fixed bug with destroying stateful objects

This commit is contained in:
kikito 2010-07-14 15:19:17 +02:00
parent bf24742c9c
commit 64f2d89281
2 changed files with 205 additions and 194 deletions

27
MiddleClass.lua Normal file → Executable file
View File

@ -58,6 +58,8 @@ Object.subclass = function(theClass, name)
_classes[theSubclass]=theSubclass --registers the new class on the list of _classes
theClass:subclassed(theSubclass) -- hook method. By default it does nothing
return theSubclass
end
@ -72,10 +74,12 @@ Object.includes = function(theClass, module, ... )
if type(module.included)=="function" then module:included(theClass, ... ) end
end
-- root of initialize and __tostring methods
-- built-in methods
Object.__classDict = {
initialize = function(instance, ...) end, -- end of the initialize() call chain
__tostring = function(instance) return ("instance of ".. instance.class.name) end
initialize = function(instance, ...) end, -- empty method
destroy = function(instance) end, -- empty method
__tostring = function(instance) return ("instance of ".. instance.class.name) end,
subclassed = function(theClass, other) end -- empty method
}
-- This allows doing tostring(obj) and Object() instead of Object:new()
@ -84,23 +88,6 @@ setmetatable(Object, { __index = Object.__classDict, __newindex = Object.__class
__call = Object.new
})
-- Getter/Setter related methods
function Object.getterFor(theClass, attr) return 'get' .. attr:gsub("^%l", string.upper) end
function Object.setterFor(theClass, attr) return 'set' .. attr:gsub("^%l", string.upper) end
function Object.getter(theClass, attributeName, defaultValue)
theClass[theClass:getterFor(attributeName)] = function(self)
if(self[attributeName]~=nil) then return self[attributeName] end
return defaultValue
end
end
function Object.setter(theClass, attributeName)
theClass[theClass:setterFor(attributeName)] = function(self, value) self[attributeName] = value end
end
function Object.getterSetter(theClass, attributeName, defaultValue)
theClass:getter(attributeName, defaultValue)
theClass:setter(attributeName)
end
-- Returns true if aClass is a subclass of other, false otherwise
function subclassOf(other, aClass)
if aClass == nil or other==nil then return false end

30
MindState.lua Normal file → Executable file
View File

@ -39,11 +39,33 @@ local _ignoredMethods = {
states=1, initialize=1,
gotoState=1, pushState=1, popState=1, popAllStates=1, getCurrentState=1, isInState=1,
enterState=1, exitState=1, pushedState=1, poppedState=1, pausedState=1, continuedState=1,
addState=1, subclass=1, includes=1
addState=1, subclass=1, includes=1, destroy=1
}
local _prevSubclass = StatefulObject.subclass -- previous way of creating subclasses (used to redefine subclass itself)
-- The State class; is the father of all State objects
local State = class('State', Object)
function State.subclass(theClass, name, theStatefulClass)
local theSubClass = Object.subclass(theClass, name)
local superDict = (theClass==State and theClass.__classDict or theStatefulClass.superclass.__classDict)
theSubClass.subclass = State.subclass
local mt = getmetatable(theSubClass)
mt.__newindex = function(_, methodName, method)
if type(method) == 'function' then
local fenv = getfenv(method)
local newenv = setmetatable( {super = superDict}, {__index = fenv, __newindex = fenv} )
setfenv( method, newenv )
end
rawset(theSubClass.__classDict, methodName, method)
end
return theSubClass
end
------------------------------------
-- INSTANCE METHODS
------------------------------------
@ -203,15 +225,17 @@ end
------------------------------------
--[[ Adds a new state to the "states" class member.
superState is optional. If nil, Object will be the parent class of the new state
superState is optional. If nil, State will be the parent class of the new state
returns the newly created state
]]
function StatefulObject.addState(theClass, stateName, superState)
superState = superState or State
--print(theClass.name, stateName, superState.name)
assert(subclassOf(StatefulObject, theClass), "Use class:addState instead of class.addState")
assert(theClass.states[stateName]==nil, "The class " .. theClass.name .. " already has a state called '" .. stateName)
assert(type(stateName)=="string", "stateName must be a string")
-- states are just regular classes. If superState is nil, this uses Object as superClass
local state = class(stateName, superState)
local state = superState:subclass(stateName, theClass)
theClass.states[stateName] = state
return state
end