-
Notifications
You must be signed in to change notification settings - Fork 6
/
Apply.lua
125 lines (90 loc) · 3.73 KB
/
Apply.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
-----------------------------------------------------------------------------------
-- Apply.lua
-- Enrique García ( enrique.garcia.cota [AT] gmail [DOT] com ) - 4 Mar 2010
-- Makes possible to treat all instances of a class
-----------------------------------------------------------------------------------
assert(Object~=nil and class~=nil, 'MiddleClass not detected. Please require it before using Apply')
assert(Invoker~=nil, 'The Apply module requires the Invoker module in order to work. Please require Invoker before requiring Apply')
--[[ Usage:
require 'middleclass' -- or similar
require 'middleclass-extras.init' -- or 'middleclass-extras'
MyClass = class('MyClass')
MyClass:includes(Apply)
function MyClass:initialize()
self.counter = 0
end -- the instance will be automatically added to the list here (after initialize)
function MyClass:count() self.counter = self.counter + 1 end
local obj1 = MyClass:new()
MyClass:apply('count')
local obj2 = MyClass:new()
MyClass:apply('count')
print(obj1.counter, obj2.counter) -- prints 2 1
-- instances will be automatically removed from the list after invoking destroy (obj1:destroy() or obj2:destroy())
]]
--------------------------------
-- PRIVATE STUFF
--------------------------------
-- The list of instances
_instances = {}
-- Creates the list of instances for a class
local function _createInstancesList(theClass)
_instances[theClass] = _instances[theClass] or _G.setmetatable({}, {__mode = "k"})
end
-- Adds an instance to the "list of instances" of its class
local function _add(theClass, instance)
if not includes(Apply, theClass) then return end
_instances[theClass][instance] = instance
_add(theClass.superclass, instance)
end
-- Removes from the "list of instances"
local function _remove(theClass, instance)
if not includes(Apply, theClass) then return end
_remove(theClass.superclass, instance)
if _instances[theClass] ~= nil then _instances[theClass][instance] = nil end
end
--------------------------------
-- PUBLIC STUFF
--------------------------------
-- The Apply module
Apply = {}
-- Applies some method to all the instances of this class, including subclasses
function Apply.apply(theClass, methodOrName, ...)
return Apply.applySorted(theClass, nil, methodOrName, ... )
end
-- Applies some method to all the instances of this class, including subclasses
-- Notes:
-- * sortFunc can be provided as a meaning of sorting (table.sort will be used). Can be nil (no order)
-- * a copy of the instances table is always made so calling removeFromApply is safe inside apply
function Apply.applySorted(theClass, sortFunc, methodOrName, ...)
local copy,i = {},1
for _,instance in pairs(_instances[theClass]) do
copy[i] = instance
i = i + 1
end
if type(sortFunc)=='function' then
table.sort(copy, sortFunc)
end
for _,instance in ipairs(copy) do
if Invoker.invoke(instance, methodOrName, ...) == false then return false end
end
return true
end
--------------------------------
-- INCLUDED
--------------------------------
-- modifies the class that includes this module. For internal use only.
function Apply:included(theClass)
if not includes(Callbacks, theClass) then
theClass:include(Callbacks)
end
theClass:before('initialize', function(instance) _add(instance.class, instance) end)
theClass:after('destroy', function(instance) _remove(instance.class, instance) end)
-- initializes the instances array for every class that includes this module
_createInstancesList(theClass)
local prevSubclass = theClass.subclass
theClass.subclass = function(aClass, ...)
local theSubClass = prevSubclass(aClass, ...)
_createInstancesList(theSubClass)
return theSubClass
end
end