Re: stateful.lua
Posted: Fri Dec 23, 2011 4:53 pm
Do you plan on making this compatible with class commons?
But with class commons it would work with hump, secs and slither as well, I assume that's why he asked it.kikito wrote:Middleclass is already compatible with it.
Code: Select all
local function _null_() end
local function goto(self, state, ...)
if self.state then (self.state._leave or _null_)(self, ...) end
self.state = state and self.states[state] or {}
return (self.state._enter or _null_)(self, ...)
end
local function stateful_index(class)
return function(self, key)
local st = rawget(self, 'state') or {}
return (st[key] or class[key])
end
end
local function add_state(class, name, methods)
assert(class.states, "Class is not stateful")
class.states[name] = methods
return class
end
local function make_stateful(class, methods)
class.states = {}
class.__index = stateful_index(class)
class.goto = goto
class.add_state = add_state
return class
end
return make_stateful
Code: Select all
make_stateful = require 'stateful'
local Enemy = class('Enemy')
make_stateful(Enemy)
function Enemy:initialize(health) self.health = health end
function Enemy:speak() print('My health is ' .. tostring(self.health)) end
Enemy:add_state('Immortal', {
_enter = function() print('I became Immortal!') end,
speak = function() print('I am UNBREAKABLE!!') end,
die = function() print('I can not die now!') end,
_leave = function() print('The gods have forsaken me') end,
})
-- alternatives:
-- local Immortal = {}
-- function Immortal:speak() (...) end
-- (...)
-- Enemy:add_state('Immortal', Immortal)
-- or:
-- Enemy.states.Immortal = { ... }
-- or even (you get the idea):
-- Enemy.states.Immortal = Immortal
local peter = Enemy:new(10)
peter:speak() --> My health is 10
peter:goto('Immortal') --> I became Immortal~
peter:speak() --> I am UNBREAKABLE!!
peter:die() --> I can not die now!
peter:goto(nil) --> The gods have forsaken me
peter:speak() -- My health is 10