~ubuntu-branches/ubuntu/karmic/gnustep-base/karmic

« back to all changes in this revision

Viewing changes to Documentation/manual/AdvancedMessaging.texi

  • Committer: Bazaar Package Importer
  • Author(s): Eric Heintzmann
  • Date: 2005-04-17 00:14:38 UTC
  • mfrom: (1.2.1 upstream) (2.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050417001438-enf0y07c9tku85z1
Tags: 1.10.3-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
@paragraphindent 0
 
2
 
 
3
@node Advanced Messaging
 
4
@chapter Advanced Messaging
 
5
@cindex advanced messaging
 
6
@cindex messaging, advanced techniques
 
7
 
 
8
Objective-C provides some additional possibilities for message routing besides
 
9
the capabilities described so far (inheritance and categories).  One of the
 
10
most important is that it is possible for an object, upon receiving a message
 
11
it has not been set up to respond to, to @i{forward} that message to another
 
12
object.  A second important capability, which forwarding relies on, is the
 
13
ability to represent method implementations directly in code.  This supports
 
14
various reflective operations as well as optimization where messages are sent
 
15
many times.
 
16
 
 
17
 
 
18
@section How Messaging Works
 
19
Sending an Objective-C message requires three types of information:
 
20
 
 
21
@itemize @bullet
 
22
@item
 
23
The message @b{receiver} - the object which is to perform the request.
 
24
 
 
25
@item
 
26
The message @b{selector} - this identifies the message, and is used to
 
27
locate the excecutable code of the corresponding @b{method} by searching the
 
28
structure of the class, and if necessary its superclasses, for an
 
29
implementation.
 
30
 
 
31
@item
 
32
The message @b{arguments} - once the implementation has been found, these are
 
33
simply passed to the method on the stack as in an ordinary function call.
 
34
@end itemize
 
35
 
 
36
In the message '@code{[taskArray insertObject: anObj atIndex: i]}', the
 
37
receiver is ``@code{taskArray}'', the selector is
 
38
``@code{insertObject:atIndex:}'', and the arguments are ``@code{anObj}'' and
 
39
``@code{i}''.  Notice that the selector includes the argument titles and both
 
40
colons, but not the argument names.  In other words, this method might have
 
41
been declared as '@code{- (void) insertObject: (id)anObject atIndex:
 
42
(unsigned)index;}', but the ``@code{anObject}'' and ``@code{index}'' are just
 
43
used for tracking the arguments within the method implementation code and not
 
44
for looking up the method itself.
 
45
 
 
46
The following sequence of events would occur on sending this message at
 
47
runtime:
 
48
 
 
49
@enumerate
 
50
@item
 
51
The internal @code{isa} pointer of the @b{receiver} (@code{taskArray}) is used
 
52
to look up its class.
 
53
 
 
54
@item
 
55
The class representation is searched for a method implementation matching the
 
56
@b{selector} (@code{insertObject:atIndex:}).  If it is not found, the class's
 
57
superclass is searched, and recursively its superclass, until an
 
58
implementation is found.
 
59
 
 
60
@item
 
61
The implementation is called, as if it were a C function, using the
 
62
@b{arguments} given (@code{anObj} and @code{i}), and the result is returned to
 
63
the code sending the message.
 
64
@end enumerate
 
65
 
 
66
In fact, when the method implementation is actually called, it additionally
 
67
receives two @i{implicit} arguments: the @b{receiver} and the @b{selector}.
 
68
These additional hidden arguments may be referred to in the source code by the
 
69
names @code{self} and @code{_cmd}.
 
70
 
 
71
The process of looking up the method implementation in the receiver at runtime
 
72
is known as dynamic binding.  This is part of what makes the language powerful
 
73
and flexible, but it is inevitably (despite clever caching strategies used in
 
74
the runtime library) a little slower than a simple function call in C.  There
 
75
are, however, ways of short-circuiting the process in cases where performance
 
76
is at a premium.  Before discussing this, we must first cover the concepts of
 
77
selectors and implementations in greater detail.
 
78
 
 
79
 
 
80
@section Selectors
 
81
 
 
82
So far we have been using the following syntax to send messages to objects:
 
83
 
 
84
@example
 
85
[myArray removeObjectIdenticalTo: anObject];
 
86
@end example
 
87
 
 
88
The example sends the message named @code{removeObjectIdenticalTo:} to
 
89
@code{myArray} with the argument @code{anObject}.
 
90
 
 
91
An alternative method of writing this is the following:
 
92
 
 
93
@example
 
94
SEL removalSelector = @@selector(removeObjectIdenticalTo:);
 
95
[myArray performSelector: removalSelector withObject: anObject];
 
96
@end example
 
97
 
 
98
Here, the first line obtains the desired method selector in the form of a
 
99
compiled representation (not the full ASCII name), and the second line sends
 
100
the message as before, but now in an explicit form.  Since the message that is
 
101
sent is now effectively a variable set at runtime, this makes it possible to
 
102
support more flexible runtime functioning.
 
103
 
 
104
 
 
105
@subsection The Target-Action Paradigm
 
106
 
 
107
One conventional way of using selectors is called the @i{target-action}
 
108
paradigm, and provides a means for, among other things, binding elements of a
 
109
graphical user interface together at runtime.
 
110
 
 
111
The idea is that a given object may serve as a flexible signal sender if it
 
112
is given a receiver (the @i{target}) and a selector (the @i{action}) at
 
113
runtime.  When the object is told to send the signal, it sends the selector
 
114
to the receiver.  In some variations, the object passes itself as an
 
115
argument.
 
116
 
 
117
The code to implement this paradigm is simple -
 
118
@example
 
119
- (id) performAction
 
120
@{
 
121
  if (target == nil || action == 0)
 
122
    @{
 
123
      return nil;       // Target or action not set ... do nothing
 
124
    @}
 
125
  if ([target respondsToSelector: action] == NO)
 
126
    @{
 
127
      return nil;       // Target cannot deal with action ... do nothing
 
128
    @}
 
129
  return [target performSelector: action withObject: self];
 
130
@}
 
131
@end example
 
132
 
 
133
As an example, consider a graphical button widget that you wish to execute
 
134
some method in your application when pressed.
 
135
 
 
136
@example
 
137
  [button setTarget: bigMachine]
 
138
  [button setAction: @@selector(startUp:)];
 
139
@end example
 
140
 
 
141
Here, @code{button} stores the given target and action in instance variables,
 
142
then when it is pressed, it internally calls a method like
 
143
@code{performAction} shown above, and sends the message ``@code{[bigMachine
 
144
startUp: button]}''.
 
145
 
 
146
If you are used to programming with events and listeners in Java, the
 
147
target-action paradigm provides a lighter-weight alternative for the most
 
148
common case where only one object needs to be informed when an event occurs.
 
149
Rather than writing or extending a special-purpose adaptor class, you just
 
150
register the method you want called directly with the actuating element.  If
 
151
you need to send the event to multiple objects, however, you would need to
 
152
write a special method to multiplex the event out.  This would be
 
153
approximately comparable effort to what is always required in Java, and is
 
154
only needed in the minority of cases.
 
155
 
 
156
 
 
157
@subsection Obtaining Selectors
 
158
 
 
159
In addition to using the compile-time @code{@@selector} operator, there are a
 
160
couple of other ways of obtaining selectors.
 
161
 
 
162
@itemize @bullet
 
163
@item
 
164
In a method implementation, you can always obtain the current selector from
 
165
the variable @code{_cmd}:
 
166
@example
 
167
- (void) removeObjectIdenticalTo: (id)anObject
 
168
@{
 
169
  SEL  mySelector = _cmd;
 
170
    // ...
 
171
@}
 
172
@end example
 
173
 
 
174
@item
 
175
At any point, you can use the @code{NSSelectorFromString()} function -
 
176
@example
 
177
  SEL  mySelector = NSSelectorFromString(@@"removeObjectIdenticalTo:");
 
178
@end example
 
179
 
 
180
In reality, you would never use @code{NSSelectorFromString} for a constant
 
181
string as shown; @code{@@selector} would do and is more efficient, since is a
 
182
compile-time operator.  Its chief utility lies in the case where the selector
 
183
name is in a variable value (for whatever reason).
 
184
 
 
185
@end itemize
 
186
 
 
187
If you ever need to test the contents of a @code{SEL} variable for equality
 
188
with another, you should use the function @code{sel_eq()} provided as part of
 
189
the GNU Objective-C runtime library.  This is necessary because, while the
 
190
compiler tries to ensure that compile-time generated references to selectors
 
191
for a particular message point to the same structure, selectors produced at
 
192
runtime, or in different compilation units, will be different and a simple
 
193
pointer equality test will not do.
 
194
 
 
195
 
 
196
@subsection Avoiding Messaging Errors when an Implementation is Not Found
 
197
 
 
198
Using @b{typed} objects as shown below, the compiler would forewarn
 
199
you if the @code{anObject} was unable to respond to the @code{alert:}
 
200
message, as it knows what type of object @code{anObject} is:
 
201
 
 
202
@example
 
203
SomeClass       *anObject;              // an instance of the 'SomeClass' class
 
204
 
 
205
anObject = [[SomeClass alloc] init];    // build and initialize the object
 
206
[anObject alert: additionalObject];     // compiler warns if 'alert:' not
 
207
                                        // defined in SomeClass or a superclass
 
208
@end example
 
209
 
 
210
However at times the compiler will not forewarn you that a message will
 
211
attempt to invoke a method that is not in the @b{receiver's} repertoire. For
 
212
instance, consider the code below where @code{anObject} is not known to
 
213
implement the @code{alert:} message:
 
214
 
 
215
@example
 
216
  id            anObject;               // arbitrary object;
 
217
 
 
218
  anObject = [[SomeClass alloc] init];  // build and initialize object
 
219
  [anObject alert: additionalObject];   // compiler cannot check whether
 
220
                                        // 'alert' is defined
 
221
@end example
 
222
 
 
223
In this case, the compiler will not issue a warning, because it only knows
 
224
that @code{anObject} is of type @code{id} @dots{} so it doesn't know what
 
225
methods the object implements.
 
226
 
 
227
At runtime, if the Objective-C runtime library fails to find a @b{method
 
228
implementation} for the @code{alert:} message in the @code{SomeClass} class
 
229
or one of its superclasses, an exception is generated.  This can be avoided
 
230
in one of two ways.
 
231
 
 
232
The first way is to check in advance whether the method is implemented:
 
233
 
 
234
@example
 
235
if ([anObject respondsToSelector: @@selector(alert:)] == YES)
 
236
  @{
 
237
    [anObject alert: additionalObject]; // send it a message.
 
238
  @}
 
239
else
 
240
  @{
 
241
    // Do something else if the object can't be alerted
 
242
  @}
 
243
@end example
 
244
 
 
245
The second way is for the object the message was sent to to @i{forward} it
 
246
somewhere else.
 
247
 
 
248
 
 
249
@section Forwarding
 
250
@cindex forwarding
 
251
 
 
252
What actually happens when the GNU Objective-C runtime is unable to find a
 
253
method implementation associated with an object for a given selector is that
 
254
the runtime instead sends a special @code{forwardInvocation:} message to the
 
255
object.  (Other Objective-C runtimes do the same, but with a slightly
 
256
different message name and structure.)  The object is then able to use the
 
257
information provided to handle the message in some way, a common mechanism
 
258
being to forward the message to another object known as a @b{delegate}, so
 
259
that the other object can deal with it.
 
260
 
 
261
@example
 
262
- (void) forwardInvocation: (NSInvocation*)invocation
 
263
@{
 
264
  if ([forwardee respondsToSelector: [invocation selector]])
 
265
    return [invocation invokeWithTarget: forwardee];
 
266
  else
 
267
    return [self doesNotRecognizeSelector: [invocation selector]];
 
268
@}
 
269
@end example
 
270
 
 
271
@itemize @bullet
 
272
@item
 
273
@b{@code{invocation}} is an instance of the special @code{NSInvocation} class
 
274
containing all the information about the original message sent, including its
 
275
@b{selector} and its arguments.
 
276
 
 
277
@item
 
278
@b{@code{forwardee}} is an instance variable containing the @code{id} of an
 
279
object which has been determined to be likely to implement methods that this
 
280
object does not.
 
281
 
 
282
@item
 
283
The @b{@code{NSInvocation}} class has a convenience method that will pass the
 
284
message on to a target object given as argument.
 
285
 
 
286
@item
 
287
The @b{@code{doesNotRecognizeSelector}} method is a fallback which is
 
288
implemented in @code{NSObject}.  Unless it has been overidden, its behavior
 
289
is to raise a runtime exception (a @code{NSInvalidArgumentException} to be
 
290
exact), which generates an error message and aborts.
 
291
@end itemize
 
292
 
 
293
Forwarding is a powerful method for creating software patterns.  One of these
 
294
is that forwarding can be used to in effect provide a form of multiple
 
295
inheritance.  Note, however that, unlike inheritance, a forwarded method will
 
296
not show up in tests like @code{respondsToSelector} and
 
297
@code{isKindOfClass:}. This is because these methods search the inheritance
 
298
path, but ignore the forwarding path.  (It is possible to override them
 
299
though.)
 
300
 
 
301
Another pattern you may come across is @i{surrogate object}: surrogates
 
302
forward messages to other objects that can be assumed to be more complex. The
 
303
@code{forwardInvocation:} method of the surrogate object receives a message
 
304
that is to be forwarded; it determines whether or not the receiver exists, and
 
305
if it does not, then it will attempt to create it. A @b{proxy} object is a
 
306
common example of a surrogate object.  A proxy object is useful in a remote
 
307
invocation context, as well as certain scenarios where you want one object to
 
308
fulfill functions of another.
 
309
 
 
310
@ignore
 
311
Need to talk about NSMethodSignature and methodSignatureForSelector?
 
312
@end ignore
 
313
 
 
314
@section Implementations
 
315
 
 
316
Recall that when a message is sent, the runtime system searches for a method
 
317
implementation associated with the recipient object for the specified
 
318
selector.  (Behind the scenes this is carried out by a function
 
319
``@code{objc_msgSend()}''.)  This may necessitate searches across multiple
 
320
superclass objects traversing upwards in the inheritance hierarchy, and takes
 
321
time.  Once the runtime finds an implementation for a class, it will cache the
 
322
information, saving time on future calls.  However, even just checking and
 
323
accessing the cache has a cost associated with it.  In performance-critical
 
324
situations, you can avoid this by holding on to an implementation yourself.
 
325
In essence, implementations are function pointers, and the compiler provides a
 
326
datatype for storing them when found at runtime:
 
327
 
 
328
@example
 
329
SEL  getObjSelector = @@selector(getObjectAtIndex:);
 
330
  // get the 'getObjectAtIndex' implementation for NSArray 'taskArray'
 
331
IMP  getObjImp = [taskArray methodForSelector: getObjSelector];
 
332
  // call the implementation as a function
 
333
id obj = (getObjImp)( taskArray, getObjSelector, i );
 
334
@end example
 
335
 
 
336
Here, we ask the runtime system to find the '@code{taskArray}' object's
 
337
implementation of '@code{getObjectAtIndex}'.  The runtime system will use the
 
338
same algorithm as if you were performing a method call to look up this code,
 
339
and then returns a function pointer to it.  In the next line, this pointer is
 
340
used to call the function in the usual C fashion.  Notice that the signature
 
341
includes both the object and the selector -- recall that these are the two
 
342
implicit arguments, @code{self} and @code{_cmd}, that every method
 
343
implementation receives.  The actual type definition for @code{IMP} allows
 
344
for a variable number of additional arguments, which are the explicit
 
345
arguments to the method call:
 
346
 
 
347
@example
 
348
typedef id (*IMP)(id, SEL, ...);
 
349
@end example
 
350
 
 
351
The return type of @code{IMP} is @code{id}.  However, not all methods return
 
352
@code{id}; for these others you can still get the implementation, but you
 
353
cannot use an @code{IMP} variable and instead must cast it yourself.  For
 
354
example, here is such a cast for a method taking a double and returning
 
355
'@code{double}':
 
356
 
 
357
@example
 
358
double (*squareFunc)( id, SEL, double );
 
359
double result;
 
360
 
 
361
squareFunc = (double (*)( id, SEL, double ))
 
362
     [mathObj methodForSelector: @@selector(squareOf:)];
 
363
 
 
364
result = squareFunc(mathObj, @@selector(squareOf:), 4);
 
365
@end example
 
366
 
 
367
You need to declare such a function pointer type for any method that returns
 
368
something besides @code{id} or @code{int}.  It is not necessary to declare the
 
369
argument list (@code{double}) as we did above; the first line could have been
 
370
``@code{double (*squareFunc)( id, SEL, @b{...} )}'' instead.
 
371
 
 
372
An excellent exposition of the amount of time saved in using
 
373
@code{methodForSelector} and other details of the innards of Objective-C and
 
374
the Foundation may be found here:
 
375
@url{http://www.mulle-kybernetik.com/artikel/Optimization/opti-3.html}.
 
376
 
 
377
You should realize that it is only worth it to acquire the @code{IMP} if you
 
378
are going to call it a large number of times, and if the code in the method
 
379
implementation itself is not large compared with the message send overhead.
 
380
In addition, you need to be careful not to call it when it might be the wrong
 
381
function.  Even when you are sure of the class of the object you are calling
 
382
it on, Objective-C is sufficiently dynamic that the correct function could
 
383
change as a program runs.  For example, a new category for a class could be
 
384
loaded, so that the implementation of a method changes.  Similarly, a class
 
385
could be loaded that poses as another, or one that was posing stops doing so.
 
386
In general, @code{IMPs} should be acquired just before they are to be used,
 
387
then dropped afterwards.
 
388
 
 
389
 
 
390
@comment Making Forwarding Transparent
 
391
 
 
392
@page