root/lu/LUObject.lua

Revision 937 (checked in by rsz, 2 years ago)

cleanup

Line 
1 --------------------------------------------------------------------------------
2 -- Title:               LUObject.lua
3 -- Description:         Like a square peg in a round hole
4 -- Author:              Raphaël Szwarc http://alt.textdrive.com/lua/
5 -- Creation Date:       February 1, 2005
6 -- Legal:               Copyright (C) 2005 Raphaël Szwarc
7 --------------------------------------------------------------------------------
8
9 -- import dependencies
10 local table = require( "table" )
11
12 -- define the class
13 local self = {}
14
15 --------------------------------------------------------------------------------
16 -- Metamethods
17 --------------------------------------------------------------------------------
18
19 local function Call( anObject, ... )
20         return anObject:new( ... )
21 end
22
23 local function Concat( anObject, anotherObject )
24         return tostring( anObject ) .. tostring( anotherObject )
25 end
26
27 local function Equal( anObject, anotherObject )
28         return anObject:equals( anotherObject )
29 end
30
31 local function LessThan( anObject, anotherObject )
32         return anObject:compare( anotherObject )
33 end
34
35 local function ToString( anObject )
36         return anObject:toString()       
37 end
38
39 --------------------------------------------------------------------------------
40 -- Object methods
41 --------------------------------------------------------------------------------
42
43 -- class loading
44 do
45         local meta = {}
46
47         meta.__call = Call
48         meta.__concat = Concat
49         meta.__eq = Equal
50         meta.__lt = LessThan
51         meta.__tostring = ToString
52        
53         setmetatable( self, meta )
54 end
55
56 -- factory method
57 function self:new( ... )
58         local anObject = {}
59         local aClass = self:class()
60        
61         setmetatable( anObject, aClass )
62                        
63         return anObject:init( ... )
64 end
65
66 -- method for instance initialization
67 function self:init()
68         return self
69 end
70
71 -- method for class initialization
72 function self:initialize()
73         self.__index = self
74         self.__call = Call
75         self.__concat = Concat
76         self.__eq = Equal
77         self.__lt = LessThan
78         self.__tostring = ToString
79
80         return self
81 end
82
83 -- method to access this class
84 function self:class()
85         local aValue = rawget( self, "_class" )
86
87         if aValue == nil then
88                 local somePackages = package[ "loaded" ]
89                
90                 for aName, anEntity in pairs( somePackages ) do
91                         if rawequal( self, anEntity ) == true then
92                                 rawset( self, "_className", aName )
93
94                                 aValue = anEntity
95                                 aValue:initialize()
96                                
97                                 break
98                         end
99                 end
100                
101                 if aValue == nil then
102                         aValue = getmetatable( self )
103                 end
104
105                 rawset( self, "_class", aValue )
106         end
107
108         return aValue
109 end
110
111 -- method to access this super class
112 function self:super()
113         local aValue = rawget( self, "_super" )
114
115         if aValue == nil then
116                 local aSuper = getmetatable( self:class() )
117                
118                 if self:isObject( aSuper ) == true then
119                         aValue = aSuper
120                         rawset( self, "_super", aValue )
121                 end
122         end
123
124         return aValue
125 end
126        
127 -- method to access this class name
128 function self:className()
129         local aValue = rawget( self, "_className" )
130
131         if aValue == nil then
132                 aValue = self:class():className()
133                 rawset( self, "_className", aValue )
134         end
135        
136         return aValue
137 end
138
139 -- method to compare the given object with this object
140 function self:compare( anObject )
141         local aDescription = self:toString():lower()
142         local anotherDescription = anObject:toString():lower()
143        
144         return aDescription < anotherDescription
145 end
146
147 -- method for equality
148 function self:equals( anObject )
149         return rawequal( self, anObject )
150 end
151
152 -- method for hashing
153 function self:hashCode()
154         local aValue = rawget( self, "_hashCode" )
155
156         if aValue == nil then
157                 aValue = tonumber( tostring( {} ):gsub( "table: ", "" ), 16 )
158                 rawset( self, "_hashCode", aValue )
159         end
160        
161         return aValue     
162 end
163
164 -- method to check if the given object is an instance of this object
165 function self:isKindOf( anObject )
166         if self:isObject( anObject ) == true then
167                 local aClass = anObject:class()
168                
169                 anObject = self:class()
170        
171                 while anObject ~= nil do
172                         if rawequal( aClass, anObject ) == true then
173                                 return true
174                         end
175                
176                         anObject = anObject:super()
177                 end
178         end
179        
180         return false
181 end
182
183 -- method to check if the given object is indeed an object
184 function self:isObject( anObject )
185         if type( anObject ) == "table" then
186                 local aMeta = getmetatable( anObject )
187                
188                 if aMeta ~= nil and aMeta.__call == Call then
189                         return true
190                 end
191         end
192        
193         return false
194 end
195
196  -- method to invoke the named method
197 function self:invoke( aMethod, ... )
198         local aTarget = self
199        
200         for aMethodName in ( aMethod or "" ):gmatch( "([^%.]+)" ) do
201                 if type( aTarget ) == "table" or getmetatable( aTarget ) ~= nil then
202                         local aFunction = aTarget[ aMethodName ]
203                        
204                         if type( aFunction ) == "function" then
205                                 aTarget = aFunction( aTarget, ... )
206                         elseif type( aTarget[ "get" ] ) == "function" then
207                                 aTarget = aTarget[ "get" ]( aTarget, aMethodName )
208                         else
209                                 aTarget = aFunction
210                                
211                                 break
212                         end
213                 else
214                         aTarget = nil
215                
216                         break
217                 end
218         end
219        
220         return aTarget
221 end
222
223  -- method to check if this object implements the given method name
224 function self:respondsTo( aMethod )
225         if type( self[ aMethod ] ) == "function" then
226                 return true
227         end
228        
229         return false
230 end
231
232 -- method to access self
233 function self:self()
234         return self
235 end
236
237 -- method for string representation
238 function self:toString()
239         return self:className() .. "@" .. self:hashCode()       
240 end
241
242 -- try to execute the given method
243 function self:try( aMethod, ... )
244         local someArguments = { ... }
245         local aLength = select( "#", ... )
246        
247         return function( catch )
248                 local aMethod = self[ aMethod ]
249                 local someResults = { pcall( aMethod, self, unpack( someArguments, 1, aLength ) )  }
250                 local aStatus = someResults[ 1 ]
251                
252                 if aStatus == true then
253                         return unpack( someResults, 2, table.maxn( someResults ) )
254                 else
255                         local anException = someResults[ 2 ]
256        
257                         if catch ~= nil then
258                                 return catch( anException, self, aMethod, unpack( someArguments, 1, aLength ) )
259                         end
260        
261                         return nil, anException
262                 end
263         end
264 end
265
266 -- method for serialization (see LUObjectWriter)
267 function self:writeObject()
268         local aTable = {}
269        
270         for aKey, aValue in pairs( self ) do
271                 if aKey:sub( 1, 1 ) == "_"
272                         and aKey:sub( 1, 2 ) ~= "__"
273                         and aKey ~= "_class"
274                         and aKey ~= "_className"
275                         and aKey ~= "_hashCode"
276                         and aKey ~= "_super" then
277                        
278                         aTable[ aKey ] = aValue
279                 end
280         end
281        
282         return aTable
283 end
284
285 return self
Note: See TracBrowser for help on using the browser.