Commit | Line | Data |
---|---|---|
d99832a2 NJ |
1 | @c -*-texinfo-*- |
2 | @c This is part of the GNU Guile Reference Manual. | |
21b6df30 | 3 | @c Copyright (C) 2008, 2009, 2011 |
d99832a2 NJ |
4 | @c Free Software Foundation, Inc. |
5 | @c See the file guile.texi for copying conditions. | |
6 | ||
a0e07ba4 NJ |
7 | @macro goops |
8 | GOOPS | |
9 | @end macro | |
10 | ||
11 | @macro guile | |
12 | Guile | |
13 | @end macro | |
14 | ||
eb12b401 NJ |
15 | @node GOOPS |
16 | @chapter GOOPS | |
a0e07ba4 | 17 | |
a0e07ba4 NJ |
18 | @goops{} is the object oriented extension to @guile{}. Its |
19 | implementation is derived from @w{STk-3.99.3} by Erick Gallesio and | |
56664c08 | 20 | version 1.3 of Gregor Kiczales' @cite{Tiny-Clos}. It is very close in |
b997e7f5 NJ |
21 | spirit to CLOS, the Common Lisp Object System, but is adapted for the |
22 | Scheme language. | |
23 | ||
24 | @goops{} is a full object oriented system, with classes, objects, | |
25 | multiple inheritance, and generic functions with multi-method | |
26 | dispatch. Furthermore its implementation relies on a meta object | |
27 | protocol --- which means that @goops{}'s core operations are themselves | |
28 | defined as methods on relevant classes, and can be customised by | |
29 | overriding or redefining those methods. | |
a0e07ba4 | 30 | |
f60a8353 NJ |
31 | To start using @goops{} you first need to import the @code{(oop goops)} |
32 | module. You can do this at the Guile REPL by evaluating: | |
33 | ||
34 | @lisp | |
35 | (use-modules (oop goops)) | |
36 | @end lisp | |
37 | @findex (oop goops) | |
38 | ||
769be03f | 39 | @menu |
b65ff721 | 40 | * Copyright Notice:: |
f60a8353 NJ |
41 | * Class Definition:: |
42 | * Instance Creation:: | |
43 | * Slot Options:: | |
44 | * Slot Description Example:: | |
45 | * Methods and Generic Functions:: | |
46 | * Inheritance:: | |
62d7cba3 | 47 | * Introspection:: |
12fe9fcf | 48 | * GOOPS Error Handling:: |
2cb8cf04 | 49 | * GOOPS Object Miscellany:: |
0b452f2c | 50 | * The Metaobject Protocol:: |
c34d74ff NJ |
51 | * Redefining a Class:: |
52 | * Changing the Class of an Instance:: | |
769be03f NJ |
53 | @end menu |
54 | ||
b65ff721 NJ |
55 | @node Copyright Notice |
56 | @section Copyright Notice | |
57 | ||
58 | The material in this chapter is partly derived from the STk Reference | |
59 | Manual written by Erick Gallesio, whose copyright notice is as follows. | |
60 | ||
61 | Copyright © 1993-1999 Erick Gallesio - I3S-CNRS/ESSI <eg@@unice.fr> | |
62 | Permission to use, copy, modify, distribute,and license this | |
63 | software and its documentation for any purpose is hereby granted, | |
64 | provided that existing copyright notices are retained in all | |
65 | copies and that this notice is included verbatim in any | |
66 | distributions. No written agreement, license, or royalty fee is | |
67 | required for any of the authorized uses. | |
68 | This software is provided ``AS IS'' without express or implied | |
69 | warranty. | |
70 | ||
71 | The material has been adapted for use in Guile, with the author's | |
72 | permission. | |
73 | ||
74 | ||
f60a8353 NJ |
75 | @node Class Definition |
76 | @section Class Definition | |
e946b0b9 | 77 | |
f60a8353 | 78 | A new class is defined with the @code{define-class} syntax: |
8445eb1d | 79 | |
f60a8353 NJ |
80 | @findex define-class |
81 | @cindex class | |
82 | @lisp | |
83 | (define-class @var{class} (@var{superclass} @dots{}) | |
84 | @var{slot-description} @dots{} | |
85 | @var{class-option} @dots{}) | |
86 | @end lisp | |
a0e07ba4 | 87 | |
f60a8353 NJ |
88 | @var{class} is the class being defined. The list of @var{superclass}es |
89 | specifies which existing classes, if any, to inherit slots and | |
90 | properties from. @dfn{Slots} hold per-instance@footnote{Usually --- but | |
91 | see also the @code{#:allocation} slot option.} data, for instances of | |
92 | that class --- like ``fields'' or ``member variables'' in other object | |
93 | oriented systems. Each @var{slot-description} gives the name of a slot | |
94 | and optionally some ``properties'' of this slot; for example its initial | |
95 | value, the name of a function which will access its value, and so on. | |
b0fc1b9f NJ |
96 | Class options, slot descriptions and inheritance are discussed more |
97 | below. | |
f60a8353 | 98 | @cindex slot |
a0e07ba4 | 99 | |
df0a1002 BT |
100 | @deffn syntax define-class name (super @dots{}) @ |
101 | slot-definition @dots{} class-option @dots{} | |
a9bf12c2 | 102 | Define a class called @var{name} that inherits from @var{super}s, with |
df0a1002 BT |
103 | direct slots defined by @var{slot-definition}s and @var{class-option}s. |
104 | The newly created class is bound to the variable name @var{name} in the | |
105 | current environment. | |
a0e07ba4 | 106 | |
a9bf12c2 NJ |
107 | Each @var{slot-definition} is either a symbol that names the slot or a |
108 | list, | |
a0e07ba4 | 109 | |
a9bf12c2 NJ |
110 | @example |
111 | (@var{slot-name-symbol} . @var{slot-options}) | |
112 | @end example | |
a0e07ba4 | 113 | |
a9bf12c2 NJ |
114 | where @var{slot-name-symbol} is a symbol and @var{slot-options} is a |
115 | list with an even number of elements. The even-numbered elements of | |
116 | @var{slot-options} (counting from zero) are slot option keywords; the | |
117 | odd-numbered elements are the corresponding values for those keywords. | |
a0e07ba4 | 118 | |
df0a1002 | 119 | Each @var{class-option} is an option keyword and corresponding value. |
a9bf12c2 | 120 | @end deffn |
a0e07ba4 | 121 | |
f60a8353 NJ |
122 | As an example, let us define a type for representing a complex number |
123 | in terms of two real numbers.@footnote{Of course Guile already | |
124 | provides complex numbers, and @code{<complex>} is in fact a predefined | |
125 | class in GOOPS; but the definition here is still useful as an | |
126 | example.} This can be done with the following class definition: | |
a0e07ba4 | 127 | |
f60a8353 NJ |
128 | @lisp |
129 | (define-class <my-complex> (<number>) | |
130 | r i) | |
131 | @end lisp | |
a0e07ba4 | 132 | |
f60a8353 NJ |
133 | This binds the variable @code{<my-complex>} to a new class whose |
134 | instances will contain two slots. These slots are called @code{r} and | |
135 | @code{i} and will hold the real and imaginary parts of a complex | |
136 | number. Note that this class inherits from @code{<number>}, which is a | |
137 | predefined class.@footnote{@code{<number>} is the direct superclass of | |
138 | the predefined class @code{<complex>}; @code{<complex>} is the | |
139 | superclass of @code{<real>}, and @code{<real>} is the superclass of | |
140 | @code{<integer>}.} | |
a0e07ba4 | 141 | |
b0fc1b9f NJ |
142 | Slot options are described in the next section. The possible class |
143 | options are as follows. | |
144 | ||
145 | @deffn {class option} #:metaclass metaclass | |
146 | The @code{#:metaclass} class option specifies the metaclass of the class | |
147 | being defined. @var{metaclass} must be a class that inherits from | |
148 | @code{<class>}. For the use of metaclasses, see @ref{Metaobjects and | |
149 | the Metaobject Protocol} and @ref{Metaclasses}. | |
150 | ||
151 | If the @code{#:metaclass} option is absent, GOOPS reuses or constructs a | |
152 | metaclass for the new class by calling @code{ensure-metaclass} | |
153 | (@pxref{Class Definition Protocol,, ensure-metaclass}). | |
154 | @end deffn | |
155 | ||
156 | @deffn {class option} #:name name | |
157 | The @code{#:name} class option specifies the new class's name. This | |
158 | name is used to identify the class whenever related objects - the class | |
159 | itself, its instances and its subclasses - are printed. | |
160 | ||
161 | If the @code{#:name} option is absent, GOOPS uses the first argument to | |
162 | @code{define-class} as the class name. | |
163 | @end deffn | |
a0e07ba4 | 164 | |
a0e07ba4 | 165 | |
f60a8353 NJ |
166 | @node Instance Creation |
167 | @section Instance Creation and Slot Access | |
a0e07ba4 | 168 | |
f60a8353 NJ |
169 | An instance (or object) of a defined class can be created with |
170 | @code{make}. @code{make} takes one mandatory parameter, which is the | |
171 | class of the instance to create, and a list of optional arguments that | |
172 | will be used to initialize the slots of the new instance. For instance | |
173 | the following form | |
174 | ||
175 | @findex make | |
176 | @cindex instance | |
177 | @lisp | |
178 | (define c (make <my-complex>)) | |
179 | @end lisp | |
180 | ||
181 | @noindent | |
182 | creates a new @code{<my-complex>} object and binds it to the Scheme | |
183 | variable @code{c}. | |
184 | ||
185 | @deffn generic make | |
df0a1002 | 186 | @deffnx method make (class <class>) initarg @dots{} |
f60a8353 | 187 | Create and return a new instance of class @var{class}, initialized using |
df0a1002 | 188 | @var{initarg} @enddots{}. |
f60a8353 | 189 | |
df0a1002 BT |
190 | In theory, @var{initarg} @dots{} can have any structure that is |
191 | understood by whatever methods get applied when the @code{initialize} | |
192 | generic function is applied to the newly allocated instance. | |
f60a8353 NJ |
193 | |
194 | In practice, specialized @code{initialize} methods would normally call | |
195 | @code{(next-method)}, and so eventually the standard GOOPS | |
196 | @code{initialize} methods are applied. These methods expect | |
197 | @var{initargs} to be a list with an even number of elements, where | |
198 | even-numbered elements (counting from zero) are keywords and | |
199 | odd-numbered elements are the corresponding values. | |
200 | ||
201 | GOOPS processes initialization argument keywords automatically for slots | |
202 | whose definition includes the @code{#:init-keyword} option (@pxref{Slot | |
203 | Options,, init-keyword}). Other keyword value pairs can only be | |
204 | processed by an @code{initialize} method that is specialized for the new | |
205 | instance's class. Any unprocessed keyword value pairs are ignored. | |
206 | @end deffn | |
207 | ||
208 | @deffn generic make-instance | |
df0a1002 | 209 | @deffnx method make-instance (class <class>) initarg @dots{} |
f60a8353 NJ |
210 | @code{make-instance} is an alias for @code{make}. |
211 | @end deffn | |
212 | ||
213 | The slots of the new complex number can be accessed using | |
214 | @code{slot-ref} and @code{slot-set!}. @code{slot-set!} sets the value | |
215 | of an object slot and @code{slot-ref} retrieves it. | |
216 | ||
217 | @findex slot-set! | |
218 | @findex slot-ref | |
219 | @lisp | |
220 | @group | |
221 | (slot-set! c 'r 10) | |
222 | (slot-set! c 'i 3) | |
223 | (slot-ref c 'r) @result{} 10 | |
224 | (slot-ref c 'i) @result{} 3 | |
225 | @end group | |
226 | @end lisp | |
227 | ||
228 | The @code{(oop goops describe)} module provides a @code{describe} | |
229 | function that is useful for seeing all the slots of an object; it prints | |
230 | the slots and their values to standard output. | |
231 | ||
232 | @lisp | |
233 | (describe c) | |
234 | @print{} | |
235 | #<<my-complex> 401d8638> is an instance of class <my-complex> | |
236 | Slots are: | |
237 | r = 10 | |
238 | i = 3 | |
239 | @end lisp | |
a0e07ba4 | 240 | |
a0e07ba4 NJ |
241 | |
242 | @node Slot Options | |
f60a8353 NJ |
243 | @section Slot Options |
244 | ||
245 | When specifying a slot (in a @code{(define-class @dots{})} form), | |
246 | various options can be specified in addition to the slot's name. Each | |
247 | option is specified by a keyword. The list of possible keywords is | |
248 | as follows. | |
a0e07ba4 | 249 | |
a0e07ba4 NJ |
250 | @deffn {slot option} #:init-value init-value |
251 | @deffnx {slot option} #:init-form init-form | |
252 | @deffnx {slot option} #:init-thunk init-thunk | |
253 | @deffnx {slot option} #:init-keyword init-keyword | |
254 | These options provide various ways to specify how to initialize the | |
f60a8353 NJ |
255 | slot's value at instance creation time. |
256 | @cindex default slot value | |
257 | ||
258 | @var{init-value} specifies a fixed initial slot value (shared across all | |
259 | new instances of the class). | |
260 | ||
261 | @var{init-thunk} specifies a thunk that will provide a default value for | |
262 | the slot. The thunk is called when a new instance is created and should | |
263 | return the desired initial slot value. | |
264 | ||
265 | @var{init-form} specifies a form that, when evaluated, will return | |
266 | an initial value for the slot. The form is evaluated each time that | |
267 | an instance of the class is created, in the lexical environment of the | |
268 | containing @code{define-class} expression. | |
269 | ||
270 | @var{init-keyword} specifies a keyword that can be used to pass an | |
271 | initial slot value to @code{make} when creating a new instance. | |
5695ccd4 NJ |
272 | |
273 | Note that, since an @code{init-value} value is shared across all | |
274 | instances of a class, you should only use it when the initial value is | |
275 | an immutable value, like a constant. If you want to initialize a slot | |
276 | with a fresh, independently mutable value, you should use | |
277 | @code{init-thunk} or @code{init-form} instead. Consider the following | |
278 | example. | |
279 | ||
280 | @example | |
281 | (define-class <chbouib> () | |
282 | (hashtab #:init-value (make-hash-table))) | |
283 | @end example | |
284 | ||
285 | @noindent | |
286 | Here only one hash table is created and all instances of | |
287 | @code{<chbouib>} have their @code{hashtab} slot refer to it. In order | |
288 | to have each instance of @code{<chbouib>} refer to a new hash table, you | |
289 | should instead write: | |
290 | ||
291 | @example | |
292 | (define-class <chbouib> () | |
293 | (hashtab #:init-thunk make-hash-table)) | |
294 | @end example | |
295 | ||
296 | @noindent | |
297 | or: | |
298 | ||
299 | @example | |
300 | (define-class <chbouib> () | |
301 | (hashtab #:init-form (make-hash-table))) | |
302 | @end example | |
a0e07ba4 NJ |
303 | |
304 | If more than one of these options is specified for the same slot, the | |
305 | order of precedence, highest first is | |
306 | ||
307 | @itemize @bullet | |
308 | @item | |
309 | @code{#:init-keyword}, if @var{init-keyword} is present in the options | |
310 | passed to @code{make} | |
311 | ||
312 | @item | |
313 | @code{#:init-thunk}, @code{#:init-form} or @code{#:init-value}. | |
314 | @end itemize | |
315 | ||
316 | If the slot definition contains more than one initialization option of | |
317 | the same precedence, the later ones are ignored. If a slot is not | |
318 | initialized at all, its value is unbound. | |
319 | ||
320 | In general, slots that are shared between more than one instance are | |
321 | only initialized at new instance creation time if the slot value is | |
322 | unbound at that time. However, if the new instance creation specifies | |
323 | a valid init keyword and value for a shared slot, the slot is | |
324 | re-initialized regardless of its previous value. | |
325 | ||
326 | Note, however, that the power of GOOPS' metaobject protocol means that | |
327 | everything written here may be customized or overridden for particular | |
328 | classes! The slot initializations described here are performed by the least | |
329 | specialized method of the generic function @code{initialize}, whose | |
330 | signature is | |
331 | ||
332 | @example | |
333 | (define-method (initialize (object <object>) initargs) ...) | |
334 | @end example | |
335 | ||
336 | The initialization of instances of any given class can be customized by | |
337 | defining a @code{initialize} method that is specialized for that class, | |
338 | and the author of the specialized method may decide to call | |
339 | @code{next-method} - which will result in a call to the next less | |
340 | specialized @code{initialize} method - at any point within the | |
341 | specialized code, or maybe not at all. In general, therefore, the | |
342 | initialization mechanisms described here may be modified or overridden by | |
343 | more specialized code, or may not be supported at all for particular | |
344 | classes. | |
345 | @end deffn | |
346 | ||
8445eb1d NJ |
347 | @deffn {slot option} #:getter getter |
348 | @deffnx {slot option} #:setter setter | |
349 | @deffnx {slot option} #:accessor accessor | |
350 | Given an object @var{obj} with slots named @code{foo} and @code{bar}, it | |
351 | is always possible to read and write those slots by calling | |
352 | @code{slot-ref} and @code{slot-set!} with the relevant slot name; for | |
353 | example: | |
354 | ||
355 | @example | |
356 | (slot-ref @var{obj} 'foo) | |
357 | (slot-set! @var{obj} 'bar 25) | |
358 | @end example | |
359 | ||
360 | The @code{#:getter}, @code{#:setter} and @code{#:accessor} options, if | |
361 | present, tell GOOPS to create generic function and method definitions | |
362 | that can be used to get and set the slot value more conveniently. | |
363 | @var{getter} specifies a generic function to which GOOPS will add a | |
364 | method for getting the slot value. @var{setter} specifies a generic | |
365 | function to which GOOPS will add a method for setting the slot value. | |
366 | @var{accessor} specifies an accessor to which GOOPS will add methods for | |
367 | both getting and setting the slot value. | |
368 | ||
369 | So if a class includes a slot definition like this: | |
370 | ||
371 | @example | |
372 | (c #:getter get-count #:setter set-count #:accessor count) | |
373 | @end example | |
374 | ||
375 | GOOPS defines generic function methods such that the slot value can be | |
376 | referenced using either the getter or the accessor - | |
377 | ||
378 | @example | |
379 | (let ((current-count (get-count obj))) @dots{}) | |
380 | (let ((current-count (count obj))) @dots{}) | |
381 | @end example | |
382 | ||
383 | - and set using either the setter or the accessor - | |
384 | ||
385 | @example | |
386 | (set-count obj (+ 1 current-count)) | |
387 | (set! (count obj) (+ 1 current-count)) | |
388 | @end example | |
389 | ||
390 | Note that | |
391 | ||
392 | @itemize @bullet | |
393 | @item | |
394 | with an accessor, the slot value is set using the generalized | |
395 | @code{set!} syntax | |
396 | ||
397 | @item | |
398 | in practice, it is unusual for a slot to use all three of these options: | |
399 | read-only, write-only and read-write slots would typically use only | |
400 | @code{#:getter}, @code{#:setter} and @code{#:accessor} options | |
401 | respectively. | |
402 | @end itemize | |
403 | ||
f60a8353 NJ |
404 | The binding of the specified names is done in the environment of the |
405 | @code{define-class} expression. If the names are already bound (in that | |
406 | environment) to values that cannot be upgraded to generic functions, | |
407 | those values are overwritten when the @code{define-class} expression is | |
408 | evaluated. For more detail, see @ref{Generic Function Internals,, | |
8445eb1d NJ |
409 | ensure-generic}. |
410 | @end deffn | |
411 | ||
412 | @deffn {slot option} #:allocation allocation | |
413 | The @code{#:allocation} option tells GOOPS how to allocate storage for | |
414 | the slot. Possible values for @var{allocation} are | |
415 | ||
416 | @itemize @bullet | |
417 | @item @code{#:instance} | |
418 | ||
f60a8353 | 419 | @findex #:instance |
8445eb1d | 420 | Indicates that GOOPS should create separate storage for this slot in |
f60a8353 NJ |
421 | each new instance of the containing class (and its subclasses). This is |
422 | the default. | |
8445eb1d NJ |
423 | |
424 | @item @code{#:class} | |
425 | ||
f60a8353 | 426 | @findex #:class |
8445eb1d NJ |
427 | Indicates that GOOPS should create storage for this slot that is shared |
428 | by all instances of the containing class (and its subclasses). In other | |
429 | words, a slot in class @var{C} with allocation @code{#:class} is shared | |
430 | by all @var{instance}s for which @code{(is-a? @var{instance} @var{c})}. | |
f60a8353 NJ |
431 | This permits defining a kind of global variable which can be accessed |
432 | only by (in)direct instances of the class which defines the slot. | |
8445eb1d NJ |
433 | |
434 | @item @code{#:each-subclass} | |
435 | ||
f60a8353 | 436 | @findex #:each-subclass |
8445eb1d NJ |
437 | Indicates that GOOPS should create storage for this slot that is shared |
438 | by all @emph{direct} instances of the containing class, and that | |
439 | whenever a subclass of the containing class is defined, GOOPS should | |
440 | create a new storage for the slot that is shared by all @emph{direct} | |
441 | instances of the subclass. In other words, a slot with allocation | |
442 | @code{#:each-subclass} is shared by all instances with the same | |
443 | @code{class-of}. | |
444 | ||
445 | @item @code{#:virtual} | |
446 | ||
f60a8353 NJ |
447 | @findex #:slot-set! |
448 | @findex #:slot-ref | |
449 | @findex #:virtual | |
8445eb1d NJ |
450 | Indicates that GOOPS should not allocate storage for this slot. The |
451 | slot definition must also include the @code{#:slot-ref} and | |
452 | @code{#:slot-set!} options to specify how to reference and set the value | |
f60a8353 | 453 | for this slot. See the example below. |
8445eb1d NJ |
454 | @end itemize |
455 | ||
8445eb1d NJ |
456 | Slot allocation options are processed when defining a new class by the |
457 | generic function @code{compute-get-n-set}, which is specialized by the | |
458 | class's metaclass. Hence new types of slot allocation can be | |
459 | implemented by defining a new metaclass and a method for | |
460 | @code{compute-get-n-set} that is specialized for the new metaclass. For | |
461 | an example of how to do this, see @ref{Customizing Class Definition}. | |
462 | @end deffn | |
463 | ||
464 | @deffn {slot option} #:slot-ref getter | |
465 | @deffnx {slot option} #:slot-set! setter | |
466 | The @code{#:slot-ref} and @code{#:slot-set!} options must be specified | |
467 | if the slot allocation is @code{#:virtual}, and are ignored otherwise. | |
468 | ||
469 | @var{getter} should be a closure taking a single @var{instance} parameter | |
470 | that returns the current slot value. @var{setter} should be a closure | |
471 | taking two parameters - @var{instance} and @var{new-val} - that sets the | |
472 | slot value to @var{new-val}. | |
473 | @end deffn | |
474 | ||
f60a8353 NJ |
475 | @node Slot Description Example |
476 | @section Illustrating Slot Description | |
8445eb1d | 477 | |
f60a8353 NJ |
478 | To illustrate slot description, we can redefine the @code{<my-complex>} |
479 | class seen before. A definition could be: | |
8445eb1d | 480 | |
f60a8353 NJ |
481 | @lisp |
482 | (define-class <my-complex> (<number>) | |
483 | (r #:init-value 0 #:getter get-r #:setter set-r! #:init-keyword #:r) | |
484 | (i #:init-value 0 #:getter get-i #:setter set-i! #:init-keyword #:i)) | |
485 | @end lisp | |
8445eb1d | 486 | |
f60a8353 NJ |
487 | @noindent |
488 | With this definition, the @code{r} and @code{i} slots are set to 0 by | |
489 | default, and can be initialised to other values by calling @code{make} | |
490 | with the @code{#:r} and @code{#:i} keywords. Also the generic functions | |
491 | @code{get-r}, @code{set-r!}, @code{get-i} and @code{set-i!} are | |
492 | automatically defined to read and write the slots. | |
8445eb1d | 493 | |
f60a8353 NJ |
494 | @lisp |
495 | (define c1 (make <my-complex> #:r 1 #:i 2)) | |
496 | (get-r c1) @result{} 1 | |
497 | (set-r! c1 12) | |
498 | (get-r c1) @result{} 12 | |
499 | (define c2 (make <my-complex> #:r 2)) | |
500 | (get-r c2) @result{} 2 | |
501 | (get-i c2) @result{} 0 | |
502 | @end lisp | |
8445eb1d | 503 | |
f60a8353 NJ |
504 | Accessors can both read and write a slot. So, another definition of the |
505 | @code{<my-complex>} class, using the @code{#:accessor} option, could be: | |
a0e07ba4 | 506 | |
f60a8353 NJ |
507 | @findex set! |
508 | @lisp | |
509 | (define-class <my-complex> (<number>) | |
510 | (r #:init-value 0 #:accessor real-part #:init-keyword #:r) | |
511 | (i #:init-value 0 #:accessor imag-part #:init-keyword #:i)) | |
512 | @end lisp | |
a0e07ba4 | 513 | |
f60a8353 NJ |
514 | @noindent |
515 | With this definition, the @code{r} slot can be read with: | |
516 | @lisp | |
517 | (real-part c) | |
518 | @end lisp | |
519 | @noindent | |
520 | and set with: | |
521 | @lisp | |
522 | (set! (real-part c) new-value) | |
523 | @end lisp | |
a0e07ba4 | 524 | |
f60a8353 NJ |
525 | Suppose now that we want to manipulate complex numbers with both |
526 | rectangular and polar coordinates. One solution could be to have a | |
527 | definition of complex numbers which uses one particular representation | |
528 | and some conversion functions to pass from one representation to the | |
529 | other. A better solution is to use virtual slots, like this: | |
a0e07ba4 | 530 | |
f60a8353 NJ |
531 | @lisp |
532 | (define-class <my-complex> (<number>) | |
533 | ;; True slots use rectangular coordinates | |
534 | (r #:init-value 0 #:accessor real-part #:init-keyword #:r) | |
535 | (i #:init-value 0 #:accessor imag-part #:init-keyword #:i) | |
536 | ;; Virtual slots access do the conversion | |
537 | (m #:accessor magnitude #:init-keyword #:magn | |
538 | #:allocation #:virtual | |
539 | #:slot-ref (lambda (o) | |
540 | (let ((r (slot-ref o 'r)) (i (slot-ref o 'i))) | |
541 | (sqrt (+ (* r r) (* i i))))) | |
542 | #:slot-set! (lambda (o m) | |
543 | (let ((a (slot-ref o 'a))) | |
544 | (slot-set! o 'r (* m (cos a))) | |
545 | (slot-set! o 'i (* m (sin a)))))) | |
546 | (a #:accessor angle #:init-keyword #:angle | |
547 | #:allocation #:virtual | |
548 | #:slot-ref (lambda (o) | |
549 | (atan (slot-ref o 'i) (slot-ref o 'r))) | |
550 | #:slot-set! (lambda(o a) | |
551 | (let ((m (slot-ref o 'm))) | |
552 | (slot-set! o 'r (* m (cos a))) | |
553 | (slot-set! o 'i (* m (sin a))))))) | |
a0e07ba4 | 554 | |
f60a8353 | 555 | @end lisp |
a0e07ba4 | 556 | |
ecb87335 | 557 | In this class definition, the magnitude @code{m} and angle @code{a} |
f60a8353 | 558 | slots are virtual, and are calculated, when referenced, from the normal |
679cceed | 559 | (i.e.@: @code{#:allocation #:instance}) slots @code{r} and @code{i}, by |
f60a8353 NJ |
560 | calling the function defined in the relevant @code{#:slot-ref} option. |
561 | Correspondingly, writing @code{m} or @code{a} leads to calling the | |
562 | function defined in the @code{#:slot-set!} option. Thus the | |
563 | following expression | |
a0e07ba4 | 564 | |
f60a8353 NJ |
565 | @findex #:slot-set! |
566 | @findex #:slot-ref | |
567 | @lisp | |
568 | (slot-set! c 'a 3) | |
569 | @end lisp | |
570 | ||
571 | @noindent | |
572 | permits to set the angle of the @code{c} complex number. | |
573 | ||
574 | @lisp | |
575 | (define c (make <my-complex> #:r 12 #:i 20)) | |
576 | (real-part c) @result{} 12 | |
577 | (angle c) @result{} 1.03037682652431 | |
578 | (slot-set! c 'i 10) | |
579 | (set! (real-part c) 1) | |
580 | (describe c) | |
581 | @print{} | |
582 | #<<my-complex> 401e9b58> is an instance of class <my-complex> | |
583 | Slots are: | |
584 | r = 1 | |
585 | i = 10 | |
586 | m = 10.0498756211209 | |
587 | a = 1.47112767430373 | |
588 | @end lisp | |
589 | ||
590 | Since initialization keywords have been defined for the four slots, we | |
591 | can now define the standard Scheme primitives @code{make-rectangular} | |
592 | and @code{make-polar}. | |
a0e07ba4 | 593 | |
f60a8353 NJ |
594 | @lisp |
595 | (define make-rectangular | |
596 | (lambda (x y) (make <my-complex> #:r x #:i y))) | |
597 | ||
598 | (define make-polar | |
599 | (lambda (x y) (make <my-complex> #:magn x #:angle y))) | |
600 | @end lisp | |
a0e07ba4 | 601 | |
f60a8353 NJ |
602 | |
603 | @node Methods and Generic Functions | |
604 | @section Methods and Generic Functions | |
605 | ||
606 | A GOOPS method is like a Scheme procedure except that it is specialized | |
607 | for a particular set of argument classes, and will only be used when the | |
608 | actual arguments in a call match the classes in the method definition. | |
609 | ||
610 | @lisp | |
611 | (define-method (+ (x <string>) (y <string>)) | |
612 | (string-append x y)) | |
613 | ||
614 | (+ "abc" "de") @result{} "abcde" | |
615 | @end lisp | |
616 | ||
617 | A method is not formally associated with any single class (as it is in | |
618 | many other object oriented languages), because a method can be | |
619 | specialized for a combination of several classes. If you've studied | |
620 | object orientation in non-Lispy languages, you may remember discussions | |
621 | such as whether a method to stretch a graphical image around a surface | |
622 | should be a method of the image class, with a surface as a parameter, or | |
623 | a method of the surface class, with an image as a parameter. In GOOPS | |
624 | you'd just write | |
625 | ||
626 | @lisp | |
627 | (define-method (stretch (im <image>) (sf <surface>)) | |
628 | ...) | |
629 | @end lisp | |
630 | ||
631 | @noindent | |
632 | and the question of which class the method is more associated with does | |
633 | not need answering. | |
634 | ||
68f4fee1 NJ |
635 | There can simultaneously be several methods with the same name but |
636 | different sets of specializing argument classes; for example: | |
637 | ||
638 | @lisp | |
639 | (define-method (+ (x <string>) (y <string)) ...) | |
640 | (define-method (+ (x <matrix>) (y <matrix>)) ...) | |
ecb87335 | 641 | (define-method (+ (f <fish>) (b <bicycle>)) ...) |
68f4fee1 NJ |
642 | (define-method (+ (a <foo>) (b <bar>) (c <baz>)) ...) |
643 | @end lisp | |
644 | ||
645 | @noindent | |
646 | A generic function is a container for the set of such methods that a | |
647 | program intends to use. | |
648 | ||
649 | If you look at a program's source code, and see @code{(+ x y)} somewhere | |
650 | in it, conceptually what is happening is that the program at that point | |
651 | calls a generic function (in this case, the generic function bound to | |
652 | the identifier @code{+}). When that happens, Guile works out which of | |
653 | the generic function's methods is the most appropriate for the arguments | |
654 | that the function is being called with; then it evaluates the method's | |
655 | code with the arguments as formal parameters. This happens every time | |
656 | that a generic function call is evaluated --- it isn't assumed that a | |
657 | given source code call will end up invoking the same method every time. | |
658 | ||
659 | Defining an identifier as a generic function is done with the | |
660 | @code{define-generic} macro. Definition of a new method is done with | |
661 | the @code{define-method} macro. Note that @code{define-method} | |
662 | automatically does a @code{define-generic} if the identifier concerned | |
663 | is not already a generic function, so often an explicit | |
664 | @code{define-generic} call is not needed. | |
665 | @findex define-generic | |
666 | @findex define-method | |
667 | ||
668 | @deffn syntax define-generic symbol | |
669 | Create a generic function with name @var{symbol} and bind it to the | |
670 | variable @var{symbol}. If @var{symbol} was previously bound to a Scheme | |
671 | procedure (or procedure-with-setter), the old procedure (and setter) is | |
672 | incorporated into the new generic function as its default procedure (and | |
673 | setter). Any other previous value, including an existing generic | |
674 | function, is discarded and replaced by a new, empty generic function. | |
675 | @end deffn | |
676 | ||
df0a1002 | 677 | @deffn syntax define-method (generic parameter @dots{}) body @dots{} |
68f4fee1 | 678 | Define a method for the generic function or accessor @var{generic} with |
df0a1002 | 679 | parameters @var{parameter}s and body @var{body} @enddots{}. |
68f4fee1 NJ |
680 | |
681 | @var{generic} is a generic function. If @var{generic} is a variable | |
682 | which is not yet bound to a generic function object, the expansion of | |
683 | @code{define-method} will include a call to @code{define-generic}. If | |
684 | @var{generic} is @code{(setter @var{generic-with-setter})}, where | |
685 | @var{generic-with-setter} is a variable which is not yet bound to a | |
686 | generic-with-setter object, the expansion will include a call to | |
687 | @code{define-accessor}. | |
688 | ||
689 | Each @var{parameter} must be either a symbol or a two-element list | |
690 | @code{(@var{symbol} @var{class})}. The symbols refer to variables in | |
df0a1002 | 691 | the body forms that will be bound to the parameters supplied by the |
68f4fee1 NJ |
692 | caller when calling this method. The @var{class}es, if present, |
693 | specify the possible combinations of parameters to which this method | |
694 | can be applied. | |
695 | ||
df0a1002 | 696 | @var{body} @dots{} are the bodies of the method definition. |
68f4fee1 NJ |
697 | @end deffn |
698 | ||
699 | @code{define-method} expressions look a little like Scheme procedure | |
700 | definitions of the form | |
701 | ||
702 | @example | |
703 | (define (name formals @dots{}) . body) | |
704 | @end example | |
705 | ||
706 | The important difference is that each formal parameter, apart from the | |
707 | possible ``rest'' argument, can be qualified by a class name: | |
708 | @code{@var{formal}} becomes @code{(@var{formal} @var{class})}. The | |
709 | meaning of this qualification is that the method being defined | |
710 | will only be applicable in a particular generic function invocation if | |
711 | the corresponding argument is an instance of @code{@var{class}} (or one of | |
712 | its subclasses). If more than one of the formal parameters is qualified | |
713 | in this way, then the method will only be applicable if each of the | |
714 | corresponding arguments is an instance of its respective qualifying class. | |
715 | ||
716 | Note that unqualified formal parameters act as though they are qualified | |
717 | by the class @code{<top>}, which GOOPS uses to mean the superclass of | |
718 | all valid Scheme types, including both primitive types and GOOPS classes. | |
719 | ||
720 | For example, if a generic function method is defined with | |
721 | @var{parameter}s @code{(s1 <square>)} and @code{(n <number>)}, that | |
722 | method is only applicable to invocations of its generic function that | |
723 | have two parameters where the first parameter is an instance of the | |
724 | @code{<square>} class and the second parameter is a number. | |
f60a8353 NJ |
725 | |
726 | @menu | |
68f4fee1 NJ |
727 | * Accessors:: |
728 | * Extending Primitives:: | |
729 | * Merging Generics:: | |
f60a8353 | 730 | * Next-method:: |
68f4fee1 NJ |
731 | * Generic Function and Method Examples:: |
732 | * Handling Invocation Errors:: | |
f60a8353 NJ |
733 | @end menu |
734 | ||
f60a8353 | 735 | |
68f4fee1 NJ |
736 | @node Accessors |
737 | @subsection Accessors | |
f60a8353 | 738 | |
68f4fee1 NJ |
739 | An accessor is a generic function that can also be used with the |
740 | generalized @code{set!} syntax (@pxref{Procedures with Setters}). Guile | |
741 | will handle a call like | |
f60a8353 | 742 | |
68f4fee1 NJ |
743 | @example |
744 | (set! (@code{accessor} @code{args}@dots{}) @code{value}) | |
745 | @end example | |
f60a8353 | 746 | |
68f4fee1 NJ |
747 | @noindent |
748 | by calling the most specialized method of @code{accessor} that matches | |
749 | the classes of @code{args} and @code{value}. @code{define-accessor} is | |
750 | used to bind an identifier to an accessor. | |
f60a8353 | 751 | |
68f4fee1 NJ |
752 | @deffn syntax define-accessor symbol |
753 | Create an accessor with name @var{symbol} and bind it to the variable | |
754 | @var{symbol}. If @var{symbol} was previously bound to a Scheme | |
755 | procedure (or procedure-with-setter), the old procedure (and setter) is | |
756 | incorporated into the new accessor as its default procedure (and | |
757 | setter). Any other previous value, including an existing generic | |
758 | function or accessor, is discarded and replaced by a new, empty | |
759 | accessor. | |
760 | @end deffn | |
f60a8353 | 761 | |
f60a8353 | 762 | |
68f4fee1 NJ |
763 | @node Extending Primitives |
764 | @subsection Extending Primitives | |
765 | ||
766 | Many of Guile's primitive procedures can be extended by giving them a | |
767 | generic function definition that operates in conjunction with their | |
768 | normal C-coded implementation. When a primitive is extended in this | |
769 | way, it behaves like a generic function with the C-coded implementation | |
770 | as its default method. | |
771 | ||
772 | This extension happens automatically if a method is defined (by a | |
773 | @code{define-method} call) for a variable whose current value is a | |
774 | primitive. But it can also be forced by calling | |
775 | @code{enable-primitive-generic!}. | |
776 | ||
777 | @deffn {primitive procedure} enable-primitive-generic! primitive | |
778 | Force the creation of a generic function definition for | |
779 | @var{primitive}. | |
780 | @end deffn | |
781 | ||
782 | Once the generic function definition for a primitive has been created, | |
783 | it can be retrieved using @code{primitive-generic-generic}. | |
784 | ||
785 | @deffn {primitive procedure} primitive-generic-generic primitive | |
786 | Return the generic function definition of @var{primitive}. | |
f60a8353 | 787 | |
68f4fee1 NJ |
788 | @code{primitive-generic-generic} raises an error if @var{primitive} |
789 | is not a primitive with generic capability. | |
790 | @end deffn | |
791 | ||
792 | @node Merging Generics | |
793 | @subsection Merging Generics | |
794 | ||
795 | GOOPS generic functions and accessors often have short, generic names. | |
796 | For example, if a vector package provides an accessor for the X | |
797 | coordinate of a vector, that accessor may just be called @code{x}. It | |
798 | doesn't need to be called, for example, @code{vector:x}, because | |
799 | GOOPS will work out, when it sees code like @code{(x @var{obj})}, that | |
800 | the vector-specific method of @code{x} should be called if @var{obj} is | |
801 | a vector. | |
802 | ||
803 | That raises the question, though, of what happens when different | |
804 | packages define a generic function with the same name. Suppose we work | |
805 | with a graphical package which needs to use two independent vector | |
806 | packages for 2D and 3D vectors respectively. If both packages export | |
807 | @code{x}, what does the code using those packages end up with? | |
808 | ||
809 | @ref{Creating Guile Modules,,duplicate binding handlers} explains how | |
810 | this is resolved for conflicting bindings in general. For generics, | |
811 | there is a special duplicates handler, @code{merge-generics}, which | |
812 | tells the module system to merge generic functions with the same name. | |
813 | Here is an example: | |
f60a8353 NJ |
814 | |
815 | @lisp | |
68f4fee1 NJ |
816 | (define-module (math 2D-vectors) |
817 | #:use-module (oop goops) | |
818 | #:export (x y ...)) | |
819 | ||
820 | (define-module (math 3D-vectors) | |
821 | #:use-module (oop goops) | |
822 | #:export (x y z ...)) | |
823 | ||
824 | (define-module (my-module) | |
21b6df30 | 825 | #:use-module (oop goops) |
68f4fee1 NJ |
826 | #:use-module (math 2D-vectors) |
827 | #:use-module (math 3D-vectors) | |
21b6df30 | 828 | #:duplicates (merge-generics)) |
f60a8353 NJ |
829 | @end lisp |
830 | ||
68f4fee1 NJ |
831 | The generic function @code{x} in @code{(my-module)} will now incorporate |
832 | all of the methods of @code{x} from both imported modules. | |
833 | ||
834 | To be precise, there will now be three distinct generic functions named | |
835 | @code{x}: @code{x} in @code{(math 2D-vectors)}, @code{x} in @code{(math | |
836 | 3D-vectors)}, and @code{x} in @code{(my-module)}; and these functions | |
837 | share their methods in an interesting and dynamic way. | |
838 | ||
839 | To explain, let's call the imported generic functions (in @code{(math | |
840 | 2D-vectors)} and @code{(math 3D-vectors)}) the @dfn{ancestors}, and the | |
841 | merged generic function (in @code{(my-module)}), the @dfn{descendant}. | |
842 | The general rule is that for any generic function G, the applicable | |
843 | methods are selected from the union of the methods of G's descendant | |
844 | functions, the methods of G itself and the methods of G's ancestor | |
845 | functions. | |
846 | ||
847 | Thus ancestor functions effectively share methods with their | |
848 | descendants, and vice versa. In the example above, @code{x} in | |
849 | @code{(math 2D-vectors)} will share the methods of @code{x} in | |
850 | @code{(my-module)} and vice versa.@footnote{But note that @code{x} in | |
851 | @code{(math 2D-vectors)} doesn't share methods with @code{x} in | |
852 | @code{(math 3D-vectors)}, so modularity is still preserved.} Sharing is | |
853 | dynamic, so adding another new method to a descendant implies adding it | |
854 | to that descendant's ancestors too. | |
855 | ||
f60a8353 NJ |
856 | @node Next-method |
857 | @subsection Next-method | |
858 | ||
859 | When you call a generic function, with a particular set of arguments, | |
860 | GOOPS builds a list of all the methods that are applicable to those | |
861 | arguments and orders them by how closely the method definitions match | |
862 | the actual argument types. It then calls the method at the top of this | |
863 | list. If the selected method's code wants to call on to the next method | |
864 | in this list, it can do so by using @code{next-method}. | |
865 | ||
866 | @lisp | |
867 | (define-method (Test (a <integer>)) (cons 'integer (next-method))) | |
868 | (define-method (Test (a <number>)) (cons 'number (next-method))) | |
869 | (define-method (Test a) (list 'top)) | |
870 | @end lisp | |
871 | ||
872 | With these definitions, | |
873 | ||
874 | @lisp | |
875 | (Test 1) @result{} (integer number top) | |
876 | (Test 1.0) @result{} (number top) | |
877 | (Test #t) @result{} (top) | |
878 | @end lisp | |
879 | ||
880 | @code{next-method} is always called as just @code{(next-method)}. The | |
881 | arguments for the next method call are always implicit, and always the | |
882 | same as for the original method call. | |
883 | ||
884 | If you want to call on to a method with the same name but with a | |
885 | different set of arguments (as you might with overloaded methods in C++, | |
886 | for example), you do not use @code{next-method}, but instead simply | |
887 | write the new call as usual: | |
888 | ||
889 | @lisp | |
890 | (define-method (Test (a <number>) min max) | |
891 | (if (and (>= a min) (<= a max)) | |
892 | (display "Number is in range\n")) | |
893 | (Test a)) | |
894 | ||
895 | (Test 2 1 10) | |
896 | @print{} | |
897 | Number is in range | |
898 | @result{} | |
899 | (integer number top) | |
900 | @end lisp | |
901 | ||
902 | (You should be careful in this case that the @code{Test} calls do not | |
903 | lead to an infinite recursion, but this consideration is just the same | |
904 | as in Scheme code in general.) | |
905 | ||
68f4fee1 NJ |
906 | @node Generic Function and Method Examples |
907 | @subsection Generic Function and Method Examples | |
908 | ||
909 | Consider the following definitions: | |
f60a8353 | 910 | |
68f4fee1 NJ |
911 | @lisp |
912 | (define-generic G) | |
913 | (define-method (G (a <integer>) b) 'integer) | |
914 | (define-method (G (a <real>) b) 'real) | |
915 | (define-method (G a b) 'top) | |
916 | @end lisp | |
917 | ||
918 | The @code{define-generic} call defines @var{G} as a generic function. | |
919 | The three next lines define methods for @var{G}. Each method uses a | |
920 | sequence of @dfn{parameter specializers} that specify when the given | |
921 | method is applicable. A specializer permits to indicate the class a | |
922 | parameter must belong to (directly or indirectly) to be applicable. If | |
923 | no specializer is given, the system defaults it to @code{<top>}. Thus, | |
924 | the first method definition is equivalent to | |
925 | ||
926 | @cindex parameter specializers | |
927 | @lisp | |
928 | (define-method (G (a <integer>) (b <top>)) 'integer) | |
929 | @end lisp | |
930 | ||
931 | Now, let's look at some possible calls to the generic function @var{G}: | |
932 | ||
933 | @lisp | |
934 | (G 2 3) @result{} integer | |
935 | (G 2 #t) @result{} integer | |
936 | (G 1.2 'a) @result{} real | |
937 | @c (G #3 'a) @result{} real @c was {\sharpsign} | |
938 | (G #t #f) @result{} top | |
939 | (G 1 2 3) @result{} error (since no method exists for 3 parameters) | |
940 | @end lisp | |
941 | ||
942 | The methods above use only one specializer per parameter list. But in | |
943 | general, any or all of a method's parameters may be specialized. | |
944 | Suppose we define now: | |
945 | ||
946 | @lisp | |
947 | (define-method (G (a <integer>) (b <number>)) 'integer-number) | |
948 | (define-method (G (a <integer>) (b <real>)) 'integer-real) | |
949 | (define-method (G (a <integer>) (b <integer>)) 'integer-integer) | |
950 | (define-method (G a (b <number>)) 'top-number) | |
951 | @end lisp | |
952 | ||
953 | @noindent With these definitions: | |
954 | ||
955 | @lisp | |
956 | (G 1 2) @result{} integer-integer | |
957 | (G 1 1.0) @result{} integer-real | |
958 | (G 1 #t) @result{} integer | |
959 | (G 'a 1) @result{} top-number | |
960 | @end lisp | |
961 | ||
962 | As a further example we shall continue to define operations on the | |
4431a337 NJ |
963 | @code{<my-complex>} class. Suppose that we want to use it to implement |
964 | complex numbers completely. For instance a definition for the addition | |
68f4fee1 | 965 | of two complex numbers could be |
f60a8353 NJ |
966 | |
967 | @lisp | |
968 | (define-method (new-+ (a <my-complex>) (b <my-complex>)) | |
969 | (make-rectangular (+ (real-part a) (real-part b)) | |
970 | (+ (imag-part a) (imag-part b)))) | |
971 | @end lisp | |
972 | ||
4431a337 NJ |
973 | To be sure that the @code{+} used in the method @code{new-+} is the |
974 | standard addition we can do: | |
f60a8353 NJ |
975 | |
976 | @lisp | |
977 | (define-generic new-+) | |
978 | ||
979 | (let ((+ +)) | |
980 | (define-method (new-+ (a <my-complex>) (b <my-complex>)) | |
981 | (make-rectangular (+ (real-part a) (real-part b)) | |
982 | (+ (imag-part a) (imag-part b))))) | |
983 | @end lisp | |
984 | ||
985 | The @code{define-generic} ensures here that @code{new-+} will be defined | |
986 | in the global environment. Once this is done, we can add methods to the | |
987 | generic function @code{new-+} which make a closure on the @code{+} | |
988 | symbol. A complete writing of the @code{new-+} methods is shown in | |
4431a337 | 989 | @ref{fig:newplus}. |
a0e07ba4 | 990 | |
4431a337 | 991 | @float Figure,fig:newplus |
f60a8353 NJ |
992 | @lisp |
993 | (define-generic new-+) | |
994 | ||
995 | (let ((+ +)) | |
996 | ||
997 | (define-method (new-+ (a <real>) (b <real>)) (+ a b)) | |
998 | ||
999 | (define-method (new-+ (a <real>) (b <my-complex>)) | |
1000 | (make-rectangular (+ a (real-part b)) (imag-part b))) | |
1001 | ||
1002 | (define-method (new-+ (a <my-complex>) (b <real>)) | |
1003 | (make-rectangular (+ (real-part a) b) (imag-part a))) | |
a0e07ba4 | 1004 | |
f60a8353 NJ |
1005 | (define-method (new-+ (a <my-complex>) (b <my-complex>)) |
1006 | (make-rectangular (+ (real-part a) (real-part b)) | |
1007 | (+ (imag-part a) (imag-part b)))) | |
a0e07ba4 | 1008 | |
f60a8353 NJ |
1009 | (define-method (new-+ (a <number>)) a) |
1010 | ||
1011 | (define-method (new-+) 0) | |
a0e07ba4 | 1012 | |
f60a8353 NJ |
1013 | (define-method (new-+ . args) |
1014 | (new-+ (car args) | |
1015 | (apply new-+ (cdr args))))) | |
1016 | ||
1017 | (set! + new-+) | |
1018 | @end lisp | |
1019 | ||
4431a337 NJ |
1020 | @caption{Extending @code{+} to handle complex numbers} |
1021 | @end float | |
a0e07ba4 | 1022 | |
68f4fee1 NJ |
1023 | We take advantage here of the fact that generic function are not obliged |
1024 | to have a fixed number of parameters. The four first methods implement | |
1025 | dyadic addition. The fifth method says that the addition of a single | |
1026 | element is this element itself. The sixth method says that using the | |
1027 | addition with no parameter always return 0 (as is also true for the | |
1028 | primitive @code{+}). The last method takes an arbitrary number of | |
1029 | parameters@footnote{The parameter list for a @code{define-method} | |
1030 | follows the conventions used for Scheme procedures. In particular it can | |
1031 | use the dot notation or a symbol to denote an arbitrary number of | |
1032 | parameters}. This method acts as a kind of @code{reduce}: it calls the | |
1033 | dyadic addition on the @emph{car} of the list and on the result of | |
1034 | applying it on its rest. To finish, the @code{set!} permits to redefine | |
1035 | the @code{+} symbol to our extended addition. | |
1036 | ||
1037 | To conclude our implementation (integration?) of complex numbers, we | |
1038 | could redefine standard Scheme predicates in the following manner: | |
f60a8353 NJ |
1039 | |
1040 | @lisp | |
1041 | (define-method (complex? c <my-complex>) #t) | |
1042 | (define-method (complex? c) #f) | |
1043 | ||
1044 | (define-method (number? n <number>) #t) | |
1045 | (define-method (number? n) #f) | |
1046 | @dots{} | |
f60a8353 NJ |
1047 | @end lisp |
1048 | ||
1049 | Standard primitives in which complex numbers are involved could also be | |
1050 | redefined in the same manner. | |
1051 | ||
1052 | ||
68f4fee1 NJ |
1053 | @node Handling Invocation Errors |
1054 | @subsection Handling Invocation Errors | |
1055 | ||
1056 | If a generic function is invoked with a combination of parameters for | |
1057 | which there is no applicable method, GOOPS raises an error. | |
1058 | ||
1059 | @deffn generic no-method | |
1060 | @deffnx method no-method (gf <generic>) args | |
1061 | When an application invokes a generic function, and no methods at all | |
1062 | have been defined for that generic function, GOOPS calls the | |
1063 | @code{no-method} generic function. The default method calls | |
1064 | @code{goops-error} with an appropriate message. | |
1065 | @end deffn | |
1066 | ||
1067 | @deffn generic no-applicable-method | |
1068 | @deffnx method no-applicable-method (gf <generic>) args | |
1069 | When an application applies a generic function to a set of arguments, | |
1070 | and no methods have been defined for those argument types, GOOPS calls | |
1071 | the @code{no-applicable-method} generic function. The default method | |
1072 | calls @code{goops-error} with an appropriate message. | |
1073 | @end deffn | |
1074 | ||
1075 | @deffn generic no-next-method | |
1076 | @deffnx method no-next-method (gf <generic>) args | |
1077 | When a generic function method calls @code{(next-method)} to invoke the | |
1078 | next less specialized method for that generic function, and no less | |
1079 | specialized methods have been defined for the current generic function | |
1080 | arguments, GOOPS calls the @code{no-next-method} generic function. The | |
1081 | default method calls @code{goops-error} with an appropriate message. | |
1082 | @end deffn | |
1083 | ||
1084 | ||
f60a8353 NJ |
1085 | @node Inheritance |
1086 | @section Inheritance | |
1087 | ||
1088 | Here are some class definitions to help illustrate inheritance: | |
1089 | ||
1090 | @lisp | |
1091 | (define-class A () a) | |
1092 | (define-class B () b) | |
1093 | (define-class C () c) | |
1094 | (define-class D (A B) d a) | |
1095 | (define-class E (A C) e c) | |
1096 | (define-class F (D E) f) | |
1097 | @end lisp | |
1098 | ||
1099 | @code{A}, @code{B}, @code{C} have a null list of superclasses. In this | |
1100 | case, the system will replace the null list by a list which only | |
1101 | contains @code{<object>}, the root of all the classes defined by | |
1102 | @code{define-class}. @code{D}, @code{E}, @code{F} use multiple | |
1103 | inheritance: each class inherits from two previously defined classes. | |
4431a337 NJ |
1104 | Those class definitions define a hierarchy which is shown in |
1105 | @ref{fig:hier}. In this figure, the class @code{<top>} is also shown; | |
1106 | this class is the superclass of all Scheme objects. In particular, | |
1107 | @code{<top>} is the superclass of all standard Scheme | |
e3c15cf7 | 1108 | types. |
4431a337 NJ |
1109 | |
1110 | @float Figure,fig:hier | |
f60a8353 NJ |
1111 | @iftex |
1112 | @center @image{hierarchy,5in} | |
1113 | @end iftex | |
1114 | @ifnottex | |
1115 | @verbatiminclude hierarchy.txt | |
1116 | @end ifnottex | |
1117 | ||
4431a337 NJ |
1118 | @caption{A class hierarchy.} |
1119 | @end float | |
f60a8353 NJ |
1120 | |
1121 | When a class has superclasses, its set of slots is calculated by taking | |
1122 | the union of its own slots and those of all its superclasses. Thus each | |
1123 | instance of D will have three slots, @code{a}, @code{b} and | |
1124 | @code{d}). The slots of a class can be discovered using the | |
1125 | @code{class-slots} primitive. For instance, | |
1126 | ||
1127 | @lisp | |
1128 | (class-slots A) @result{} ((a)) | |
1129 | (class-slots E) @result{} ((a) (e) (c)) | |
1130 | (class-slots F) @result{} ((e) (c) (b) (d) (a) (f)) | |
1131 | @end lisp | |
1132 | ||
1133 | @noindent | |
1134 | The ordering of the returned slots is not significant. | |
1135 | ||
1136 | @menu | |
68f4fee1 NJ |
1137 | * Class Precedence List:: |
1138 | * Sorting Methods:: | |
f60a8353 NJ |
1139 | @end menu |
1140 | ||
1141 | ||
68f4fee1 NJ |
1142 | @node Class Precedence List |
1143 | @subsection Class Precedence List | |
1144 | ||
1145 | What happens when a class inherits from two or more superclasses that | |
1146 | have a slot with the same name but incompatible definitions --- for | |
1147 | example, different init values or slot allocations? We need a rule for | |
1148 | deciding which slot definition the derived class ends up with, and this | |
1149 | rule is provided by the class's @dfn{Class Precedence | |
1150 | List}.@footnote{This section is an adaptation of material from Jeff | |
1151 | Dalton's (J.Dalton@@ed.ac.uk) @cite{Brief introduction to CLOS}} | |
a0e07ba4 | 1152 | |
68f4fee1 NJ |
1153 | Another problem arises when invoking a generic function, and there is |
1154 | more than one method that could apply to the call arguments. Here we | |
1155 | need a way of ordering the applicable methods, so that Guile knows which | |
1156 | method to use first, which to use next if that method calls | |
1157 | @code{next-method}, and so on. One of the ingredients for this ordering | |
1158 | is determining, for each given call argument, which of the specializing | |
1159 | classes, from each applicable method's definition, is the most specific | |
1160 | for that argument; and here again the class precedence list helps. | |
a0e07ba4 | 1161 | |
68f4fee1 NJ |
1162 | If inheritance was restricted such that each class could only have one |
1163 | superclass --- which is known as @dfn{single} inheritance --- class | |
1164 | ordering would be easy. The rule would be simply that a subclass is | |
1165 | considered more specific than its superclass. | |
a0e07ba4 | 1166 | |
68f4fee1 NJ |
1167 | With multiple inheritance, ordering is less obvious, and we have to |
1168 | impose an arbitrary rule to determine precedence. Suppose we have | |
a0e07ba4 | 1169 | |
f60a8353 NJ |
1170 | @lisp |
1171 | (define-class X () | |
1172 | (x #:init-value 1)) | |
1173 | ||
1174 | (define-class Y () | |
1175 | (x #:init-value 2)) | |
1176 | ||
1177 | (define-class Z (X Y) | |
1178 | (@dots{})) | |
1179 | @end lisp | |
1180 | ||
68f4fee1 NJ |
1181 | @noindent |
1182 | Clearly the @code{Z} class is more specific than @code{X} or @code{Y}, | |
1183 | for instances of @code{Z}. But which is more specific out of @code{X} | |
1184 | and @code{Y} --- and hence, for the definitions above, which | |
1185 | @code{#:init-value} will take effect when creating an instance of | |
1186 | @code{Z}? The rule in @goops{} is that the superclasses listed earlier | |
1187 | are more specific than those listed later. Hence @code{X} is more | |
1188 | specific than @code{Y}, and the @code{#:init-value} for slot @code{x} in | |
1189 | instances of @code{Z} will be 1. | |
1190 | ||
1191 | Hence there is a linear ordering for a class and all its | |
1192 | superclasses, from most specific to least specific, and this ordering is | |
1193 | called the Class Precedence List of the class. | |
1194 | ||
1195 | In fact the rules above are not quite enough to always determine a | |
1196 | unique order, but they give an idea of how things work. For example, | |
1197 | for the @code{F} class shown in @ref{fig:hier}, the class precedence | |
1198 | list is | |
f60a8353 NJ |
1199 | |
1200 | @example | |
1201 | (f d e a c b <object> <top>) | |
a0e07ba4 NJ |
1202 | @end example |
1203 | ||
68f4fee1 NJ |
1204 | @noindent |
1205 | In cases where there is any ambiguity (like this one), it is a bad idea | |
1206 | for programmers to rely on exactly what the order is. If the order for | |
1207 | some superclasses is important, it can be expressed directly in the | |
1208 | class definition. | |
f60a8353 | 1209 | |
68f4fee1 NJ |
1210 | The precedence list of a class can be obtained by calling |
1211 | @code{class-precedence-list}. This function returns a ordered list | |
1212 | whose first element is the most specific class. For instance: | |
f60a8353 NJ |
1213 | |
1214 | @lisp | |
1215 | (class-precedence-list B) @result{} (#<<class> B 401b97c8> | |
1216 | #<<class> <object> 401e4a10> | |
1217 | #<<class> <top> 4026a9d8>) | |
1218 | @end lisp | |
1219 | ||
68f4fee1 NJ |
1220 | @noindent |
1221 | Or for a more immediately readable result: | |
f60a8353 NJ |
1222 | |
1223 | @lisp | |
1224 | (map class-name (class-precedence-list B)) @result{} (B <object> <top>) | |
1225 | @end lisp | |
1226 | ||
1227 | ||
68f4fee1 NJ |
1228 | @node Sorting Methods |
1229 | @subsection Sorting Methods | |
1230 | ||
1231 | Now, with the idea of the class precedence list, we can state precisely | |
1232 | how the possible methods are sorted when more than one of the methods of | |
1233 | a generic function are applicable to the call arguments. | |
1234 | ||
1235 | The rules are that | |
1236 | @itemize | |
1237 | @item | |
1238 | the applicable methods are sorted in order of specificity, and the most | |
1239 | specific method is used first, then the next if that method calls | |
1240 | @code{next-method}, and so on | |
1241 | ||
1242 | @item | |
1243 | a method M1 is more specific than another method M2 if the first | |
1244 | specializing class that differs, between the definitions of M1 and M2, | |
1245 | is more specific, in M1's definition, for the corresponding actual call | |
1246 | argument, than the specializing class in M2's definition | |
1247 | ||
1248 | @item | |
1249 | a class C1 is more specific than another class C2, for an object of | |
1250 | actual class C, if C1 comes before C2 in C's class precedence list. | |
1251 | @end itemize | |
1252 | ||
1253 | ||
62d7cba3 NJ |
1254 | @node Introspection |
1255 | @section Introspection | |
f60a8353 | 1256 | |
dc08a490 NJ |
1257 | @dfn{Introspection}, or @dfn{reflection}, means being able to obtain |
1258 | information dynamically about GOOPS objects. It is perhaps best | |
1259 | illustrated by considering an object oriented language that does not | |
1260 | provide any introspection, namely C++. | |
f60a8353 | 1261 | |
62d7cba3 NJ |
1262 | Nothing in C++ allows a running program to obtain answers to the following |
1263 | types of question: | |
f60a8353 | 1264 | |
62d7cba3 NJ |
1265 | @itemize @bullet |
1266 | @item | |
1267 | What are the data members of this object or class? | |
f60a8353 | 1268 | |
62d7cba3 NJ |
1269 | @item |
1270 | What classes does this class inherit from? | |
f60a8353 | 1271 | |
62d7cba3 NJ |
1272 | @item |
1273 | Is this method call virtual or non-virtual? | |
1274 | ||
1275 | @item | |
1276 | If I invoke @code{Employee::adjustHoliday()}, what class contains the | |
1277 | @code{adjustHoliday()} method that will be applied? | |
1278 | @end itemize | |
1279 | ||
1280 | In C++, answers to such questions can only be determined by looking at | |
1281 | the source code, if you have access to it. GOOPS, on the other hand, | |
1282 | includes procedures that allow answers to these questions --- or their | |
1283 | GOOPS equivalents --- to be obtained dynamically, at run time. | |
a0e07ba4 NJ |
1284 | |
1285 | @menu | |
62d7cba3 | 1286 | * Classes:: |
62d7cba3 | 1287 | * Instances:: |
c7b15458 | 1288 | * Slots:: |
62d7cba3 | 1289 | * Generic Functions:: |
3617da95 | 1290 | * Accessing Slots:: |
a0e07ba4 NJ |
1291 | @end menu |
1292 | ||
62d7cba3 NJ |
1293 | @node Classes |
1294 | @subsection Classes | |
a0e07ba4 | 1295 | |
dc08a490 NJ |
1296 | A GOOPS class is itself an instance of the @code{<class>} class, or of a |
1297 | subclass of @code{<class>}. The definition of the @code{<class>} class | |
1298 | has slots that are used to describe the properties of a class, including | |
1299 | the following. | |
1300 | ||
62d7cba3 | 1301 | @deffn {primitive procedure} class-name class |
dc08a490 NJ |
1302 | Return the name of class @var{class}. This is the value of |
1303 | @var{class}'s @code{name} slot. | |
62d7cba3 | 1304 | @end deffn |
a0e07ba4 | 1305 | |
62d7cba3 | 1306 | @deffn {primitive procedure} class-direct-supers class |
dc08a490 NJ |
1307 | Return a list containing the direct superclasses of @var{class}. This |
1308 | is the value of @var{class}'s @code{direct-supers} slot. | |
a0e07ba4 NJ |
1309 | @end deffn |
1310 | ||
62d7cba3 NJ |
1311 | @deffn {primitive procedure} class-direct-slots class |
1312 | Return a list containing the slot definitions of the direct slots of | |
dc08a490 | 1313 | @var{class}. This is the value of @var{class}'s @code{direct-slots} |
62d7cba3 NJ |
1314 | slot. |
1315 | @end deffn | |
a0e07ba4 | 1316 | |
62d7cba3 | 1317 | @deffn {primitive procedure} class-direct-subclasses class |
dc08a490 NJ |
1318 | Return a list containing the direct subclasses of @var{class}. This is |
1319 | the value of @var{class}'s @code{direct-subclasses} slot. | |
a0e07ba4 NJ |
1320 | @end deffn |
1321 | ||
62d7cba3 NJ |
1322 | @deffn {primitive procedure} class-direct-methods class |
1323 | Return a list of all the generic function methods that use @var{class} | |
dc08a490 NJ |
1324 | as a formal parameter specializer. This is the value of @var{class}'s |
1325 | @code{direct-methods} slot. | |
62d7cba3 | 1326 | @end deffn |
a0e07ba4 | 1327 | |
62d7cba3 NJ |
1328 | @deffn {primitive procedure} class-precedence-list class |
1329 | Return the class precedence list for class @var{class} (@pxref{Class | |
dc08a490 | 1330 | Precedence List}). This is the value of @var{class}'s @code{cpl} slot. |
62d7cba3 | 1331 | @end deffn |
a0e07ba4 | 1332 | |
62d7cba3 | 1333 | @deffn {primitive procedure} class-slots class |
dc08a490 NJ |
1334 | Return a list containing the slot definitions for all @var{class}'s |
1335 | slots, including any slots that are inherited from superclasses. This | |
1336 | is the value of @var{class}'s @code{slots} slot. | |
62d7cba3 | 1337 | @end deffn |
a0e07ba4 | 1338 | |
62d7cba3 NJ |
1339 | @deffn procedure class-subclasses class |
1340 | Return a list of all subclasses of @var{class}. | |
a0e07ba4 NJ |
1341 | @end deffn |
1342 | ||
62d7cba3 NJ |
1343 | @deffn procedure class-methods class |
1344 | Return a list of all methods that use @var{class} or a subclass of | |
1345 | @var{class} as one of its formal parameter specializers. | |
1346 | @end deffn | |
a0e07ba4 | 1347 | |
dc08a490 | 1348 | |
c7b15458 NJ |
1349 | @node Instances |
1350 | @subsection Instances | |
1351 | ||
1352 | @deffn {primitive procedure} class-of value | |
1353 | Return the GOOPS class of any Scheme @var{value}. | |
1354 | @end deffn | |
1355 | ||
1356 | @deffn {primitive procedure} instance? object | |
1357 | Return @code{#t} if @var{object} is any GOOPS instance, otherwise | |
1358 | @code{#f}. | |
1359 | @end deffn | |
1360 | ||
1361 | @deffn procedure is-a? object class | |
1362 | Return @code{#t} if @var{object} is an instance of @var{class} or one of | |
1363 | its subclasses. | |
1364 | @end deffn | |
1365 | ||
1366 | You can use the @code{is-a?} predicate to ask whether any given value | |
1367 | belongs to a given class, or @code{class-of} to discover the class of a | |
1368 | given value. Note that when GOOPS is loaded (by code using the | |
1369 | @code{(oop goops)} module) built-in classes like @code{<string>}, | |
1370 | @code{<list>} and @code{<number>} are automatically set up, | |
1371 | corresponding to all Guile Scheme types. | |
1372 | ||
1373 | @lisp | |
1374 | (is-a? 2.3 <number>) @result{} #t | |
1375 | (is-a? 2.3 <real>) @result{} #t | |
1376 | (is-a? 2.3 <string>) @result{} #f | |
1377 | (is-a? '("a" "b") <string>) @result{} #f | |
1378 | (is-a? '("a" "b") <list>) @result{} #t | |
1379 | (is-a? (car '("a" "b")) <string>) @result{} #t | |
1380 | (is-a? <string> <class>) @result{} #t | |
1381 | (is-a? <class> <string>) @result{} #f | |
1382 | ||
1383 | (class-of 2.3) @result{} #<<class> <real> 908c708> | |
1384 | (class-of #(1 2 3)) @result{} #<<class> <vector> 908cd20> | |
1385 | (class-of <string>) @result{} #<<class> <class> 8bd3e10> | |
1386 | (class-of <class>) @result{} #<<class> <class> 8bd3e10> | |
1387 | @end lisp | |
1388 | ||
1389 | ||
62d7cba3 NJ |
1390 | @node Slots |
1391 | @subsection Slots | |
a0e07ba4 | 1392 | |
62d7cba3 NJ |
1393 | @deffn procedure class-slot-definition class slot-name |
1394 | Return the slot definition for the slot named @var{slot-name} in class | |
1395 | @var{class}. @var{slot-name} should be a symbol. | |
a0e07ba4 NJ |
1396 | @end deffn |
1397 | ||
62d7cba3 NJ |
1398 | @deffn procedure slot-definition-name slot-def |
1399 | Extract and return the slot name from @var{slot-def}. | |
a0e07ba4 NJ |
1400 | @end deffn |
1401 | ||
62d7cba3 NJ |
1402 | @deffn procedure slot-definition-options slot-def |
1403 | Extract and return the slot options from @var{slot-def}. | |
1404 | @end deffn | |
a0e07ba4 | 1405 | |
62d7cba3 NJ |
1406 | @deffn procedure slot-definition-allocation slot-def |
1407 | Extract and return the slot allocation option from @var{slot-def}. This | |
1408 | is the value of the @code{#:allocation} keyword (@pxref{Slot Options,, | |
1409 | allocation}), or @code{#:instance} if the @code{#:allocation} keyword is | |
1410 | absent. | |
1411 | @end deffn | |
a0e07ba4 | 1412 | |
62d7cba3 NJ |
1413 | @deffn procedure slot-definition-getter slot-def |
1414 | Extract and return the slot getter option from @var{slot-def}. This is | |
1415 | the value of the @code{#:getter} keyword (@pxref{Slot Options,, | |
1416 | getter}), or @code{#f} if the @code{#:getter} keyword is absent. | |
a0e07ba4 NJ |
1417 | @end deffn |
1418 | ||
62d7cba3 NJ |
1419 | @deffn procedure slot-definition-setter slot-def |
1420 | Extract and return the slot setter option from @var{slot-def}. This is | |
1421 | the value of the @code{#:setter} keyword (@pxref{Slot Options,, | |
1422 | setter}), or @code{#f} if the @code{#:setter} keyword is absent. | |
1423 | @end deffn | |
a0e07ba4 | 1424 | |
62d7cba3 NJ |
1425 | @deffn procedure slot-definition-accessor slot-def |
1426 | Extract and return the slot accessor option from @var{slot-def}. This | |
1427 | is the value of the @code{#:accessor} keyword (@pxref{Slot Options,, | |
1428 | accessor}), or @code{#f} if the @code{#:accessor} keyword is absent. | |
a0e07ba4 NJ |
1429 | @end deffn |
1430 | ||
62d7cba3 NJ |
1431 | @deffn procedure slot-definition-init-value slot-def |
1432 | Extract and return the slot init-value option from @var{slot-def}. This | |
1433 | is the value of the @code{#:init-value} keyword (@pxref{Slot Options,, | |
1434 | init-value}), or the unbound value if the @code{#:init-value} keyword is | |
1435 | absent. | |
1436 | @end deffn | |
a0e07ba4 | 1437 | |
62d7cba3 NJ |
1438 | @deffn procedure slot-definition-init-form slot-def |
1439 | Extract and return the slot init-form option from @var{slot-def}. This | |
1440 | is the value of the @code{#:init-form} keyword (@pxref{Slot Options,, | |
1441 | init-form}), or the unbound value if the @code{#:init-form} keyword is | |
1442 | absent. | |
1443 | @end deffn | |
a0e07ba4 | 1444 | |
62d7cba3 NJ |
1445 | @deffn procedure slot-definition-init-thunk slot-def |
1446 | Extract and return the slot init-thunk option from @var{slot-def}. This | |
1447 | is the value of the @code{#:init-thunk} keyword (@pxref{Slot Options,, | |
1448 | init-thunk}), or @code{#f} if the @code{#:init-thunk} keyword is absent. | |
1449 | @end deffn | |
a0e07ba4 | 1450 | |
62d7cba3 NJ |
1451 | @deffn procedure slot-definition-init-keyword slot-def |
1452 | Extract and return the slot init-keyword option from @var{slot-def}. | |
1453 | This is the value of the @code{#:init-keyword} keyword (@pxref{Slot | |
1454 | Options,, init-keyword}), or @code{#f} if the @code{#:init-keyword} | |
1455 | keyword is absent. | |
a0e07ba4 NJ |
1456 | @end deffn |
1457 | ||
62d7cba3 NJ |
1458 | @deffn procedure slot-init-function class slot-name |
1459 | Return the initialization function for the slot named @var{slot-name} in | |
1460 | class @var{class}. @var{slot-name} should be a symbol. | |
a0e07ba4 | 1461 | |
62d7cba3 NJ |
1462 | The returned initialization function incorporates the effects of the |
1463 | standard @code{#:init-thunk}, @code{#:init-form} and @code{#:init-value} | |
1464 | slot options. These initializations can be overridden by the | |
1465 | @code{#:init-keyword} slot option or by a specialized @code{initialize} | |
1466 | method, so, in general, the function returned by | |
1467 | @code{slot-init-function} may be irrelevant. For a fuller discussion, | |
1468 | see @ref{Slot Options,, init-value}. | |
a0e07ba4 NJ |
1469 | @end deffn |
1470 | ||
62d7cba3 NJ |
1471 | |
1472 | @node Generic Functions | |
1473 | @subsection Generic Functions | |
1474 | ||
dc08a490 NJ |
1475 | A generic function is an instance of the @code{<generic>} class, or of a |
1476 | subclass of @code{<generic>}. The definition of the @code{<generic>} | |
1477 | class has slots that are used to describe the properties of a generic | |
1478 | function. | |
1479 | ||
62d7cba3 NJ |
1480 | @deffn {primitive procedure} generic-function-name gf |
1481 | Return the name of generic function @var{gf}. | |
1482 | @end deffn | |
1483 | ||
1484 | @deffn {primitive procedure} generic-function-methods gf | |
dc08a490 NJ |
1485 | Return a list of the methods of generic function @var{gf}. This is the |
1486 | value of @var{gf}'s @code{methods} slot. | |
62d7cba3 NJ |
1487 | @end deffn |
1488 | ||
dc08a490 NJ |
1489 | Similarly, a method is an instance of the @code{<method>} class, or of a |
1490 | subclass of @code{<method>}; and the definition of the @code{<method>} | |
1491 | class has slots that are used to describe the properties of a method. | |
62d7cba3 NJ |
1492 | |
1493 | @deffn {primitive procedure} method-generic-function method | |
dc08a490 NJ |
1494 | Return the generic function that @var{method} belongs to. This is the |
1495 | value of @var{method}'s @code{generic-function} slot. | |
62d7cba3 NJ |
1496 | @end deffn |
1497 | ||
1498 | @deffn {primitive procedure} method-specializers method | |
dc08a490 NJ |
1499 | Return a list of @var{method}'s formal parameter specializers . This is |
1500 | the value of @var{method}'s @code{specializers} slot. | |
62d7cba3 NJ |
1501 | @end deffn |
1502 | ||
1503 | @deffn {primitive procedure} method-procedure method | |
dc08a490 NJ |
1504 | Return the procedure that implements @var{method}. This is the value of |
1505 | @var{method}'s @code{procedure} slot. | |
62d7cba3 NJ |
1506 | @end deffn |
1507 | ||
1508 | @deffn generic method-source | |
1509 | @deffnx method method-source (m <method>) | |
1510 | Return an expression that prints to show the definition of method | |
1511 | @var{m}. | |
1512 | ||
1513 | @example | |
1514 | (define-generic cube) | |
1515 | ||
1516 | (define-method (cube (n <number>)) | |
1517 | (* n n n)) | |
1518 | ||
1519 | (map method-source (generic-function-methods cube)) | |
1520 | @result{} | |
1521 | ((method ((n <number>)) (* n n n))) | |
1522 | @end example | |
1523 | @end deffn | |
1524 | ||
1525 | ||
62d7cba3 | 1526 | @node Accessing Slots |
3617da95 | 1527 | @subsection Accessing Slots |
62d7cba3 NJ |
1528 | |
1529 | Any slot, regardless of its allocation, can be queried, referenced and | |
1530 | set using the following four primitive procedures. | |
1531 | ||
1532 | @deffn {primitive procedure} slot-exists? obj slot-name | |
1533 | Return @code{#t} if @var{obj} has a slot with name @var{slot-name}, | |
1534 | otherwise @code{#f}. | |
1535 | @end deffn | |
1536 | ||
1537 | @deffn {primitive procedure} slot-bound? obj slot-name | |
1538 | Return @code{#t} if the slot named @var{slot-name} in @var{obj} has a | |
1539 | value, otherwise @code{#f}. | |
1540 | ||
1541 | @code{slot-bound?} calls the generic function @code{slot-missing} if | |
9320479a NJ |
1542 | @var{obj} does not have a slot called @var{slot-name} (@pxref{Accessing |
1543 | Slots, slot-missing}). | |
62d7cba3 NJ |
1544 | @end deffn |
1545 | ||
1546 | @deffn {primitive procedure} slot-ref obj slot-name | |
1547 | Return the value of the slot named @var{slot-name} in @var{obj}. | |
1548 | ||
1549 | @code{slot-ref} calls the generic function @code{slot-missing} if | |
9320479a NJ |
1550 | @var{obj} does not have a slot called @var{slot-name} (@pxref{Accessing |
1551 | Slots, slot-missing}). | |
62d7cba3 NJ |
1552 | |
1553 | @code{slot-ref} calls the generic function @code{slot-unbound} if the | |
9320479a NJ |
1554 | named slot in @var{obj} does not have a value (@pxref{Accessing Slots, |
1555 | slot-unbound}). | |
62d7cba3 NJ |
1556 | @end deffn |
1557 | ||
1558 | @deffn {primitive procedure} slot-set! obj slot-name value | |
1559 | Set the value of the slot named @var{slot-name} in @var{obj} to @var{value}. | |
1560 | ||
1561 | @code{slot-set!} calls the generic function @code{slot-missing} if | |
9320479a NJ |
1562 | @var{obj} does not have a slot called @var{slot-name} (@pxref{Accessing |
1563 | Slots, slot-missing}). | |
62d7cba3 NJ |
1564 | @end deffn |
1565 | ||
1566 | GOOPS stores information about slots in classes. Internally, | |
1567 | all of these procedures work by looking up the slot definition for the | |
1568 | slot named @var{slot-name} in the class @code{(class-of | |
1569 | @var{obj})}, and then using the slot definition's ``getter'' and | |
1570 | ``setter'' closures to get and set the slot value. | |
1571 | ||
1572 | The next four procedures differ from the previous ones in that they take | |
1573 | the class as an explicit argument, rather than assuming | |
1574 | @code{(class-of @var{obj})}. Therefore they allow you to apply the | |
1575 | ``getter'' and ``setter'' closures of a slot definition in one class to | |
1576 | an instance of a different class. | |
1577 | ||
1578 | @deffn {primitive procedure} slot-exists-using-class? class obj slot-name | |
1579 | Return @code{#t} if @var{class} has a slot definition for a slot with | |
1580 | name @var{slot-name}, otherwise @code{#f}. | |
1581 | @end deffn | |
1582 | ||
1583 | @deffn {primitive procedure} slot-bound-using-class? class obj slot-name | |
1584 | Return @code{#t} if applying @code{slot-ref-using-class} to the same | |
1585 | arguments would call the generic function @code{slot-unbound}, otherwise | |
1586 | @code{#f}. | |
1587 | ||
1588 | @code{slot-bound-using-class?} calls the generic function | |
1589 | @code{slot-missing} if @var{class} does not have a slot definition for a | |
9320479a | 1590 | slot called @var{slot-name} (@pxref{Accessing Slots, |
62d7cba3 NJ |
1591 | slot-missing}). |
1592 | @end deffn | |
1593 | ||
1594 | @deffn {primitive procedure} slot-ref-using-class class obj slot-name | |
1595 | Apply the ``getter'' closure for the slot named @var{slot-name} in | |
1596 | @var{class} to @var{obj}, and return its result. | |
1597 | ||
1598 | @code{slot-ref-using-class} calls the generic function | |
1599 | @code{slot-missing} if @var{class} does not have a slot definition for a | |
9320479a | 1600 | slot called @var{slot-name} (@pxref{Accessing Slots, |
62d7cba3 NJ |
1601 | slot-missing}). |
1602 | ||
1603 | @code{slot-ref-using-class} calls the generic function | |
1604 | @code{slot-unbound} if the application of the ``getter'' closure to | |
9320479a | 1605 | @var{obj} returns an unbound value (@pxref{Accessing Slots, |
62d7cba3 NJ |
1606 | slot-unbound}). |
1607 | @end deffn | |
1608 | ||
1609 | @deffn {primitive procedure} slot-set-using-class! class obj slot-name value | |
1610 | Apply the ``setter'' closure for the slot named @var{slot-name} in | |
1611 | @var{class} to @var{obj} and @var{value}. | |
1612 | ||
1613 | @code{slot-set-using-class!} calls the generic function | |
1614 | @code{slot-missing} if @var{class} does not have a slot definition for a | |
9320479a | 1615 | slot called @var{slot-name} (@pxref{Accessing Slots, slot-missing}). |
62d7cba3 NJ |
1616 | @end deffn |
1617 | ||
62d7cba3 NJ |
1618 | Slots whose allocation is per-class rather than per-instance can be |
1619 | referenced and set without needing to specify any particular instance. | |
1620 | ||
1621 | @deffn procedure class-slot-ref class slot-name | |
1622 | Return the value of the slot named @var{slot-name} in class @var{class}. | |
1623 | The named slot must have @code{#:class} or @code{#:each-subclass} | |
1624 | allocation (@pxref{Slot Options,, allocation}). | |
1625 | ||
1626 | If there is no such slot with @code{#:class} or @code{#:each-subclass} | |
1627 | allocation, @code{class-slot-ref} calls the @code{slot-missing} generic | |
1628 | function with arguments @var{class} and @var{slot-name}. Otherwise, if | |
1629 | the slot value is unbound, @code{class-slot-ref} calls the | |
1630 | @code{slot-unbound} generic function, with the same arguments. | |
1631 | @end deffn | |
1632 | ||
1633 | @deffn procedure class-slot-set! class slot-name value | |
1634 | Set the value of the slot named @var{slot-name} in class @var{class} to | |
1635 | @var{value}. The named slot must have @code{#:class} or | |
1636 | @code{#:each-subclass} allocation (@pxref{Slot Options,, allocation}). | |
1637 | ||
1638 | If there is no such slot with @code{#:class} or @code{#:each-subclass} | |
1639 | allocation, @code{class-slot-ref} calls the @code{slot-missing} generic | |
1640 | function with arguments @var{class} and @var{slot-name}. | |
1641 | @end deffn | |
1642 | ||
9320479a NJ |
1643 | When a @code{slot-ref} or @code{slot-set!} call specifies a non-existent |
1644 | slot name, or tries to reference a slot whose value is unbound, GOOPS | |
1645 | calls one of the following generic functions. | |
1646 | ||
1647 | @deffn generic slot-missing | |
1648 | @deffnx method slot-missing (class <class>) slot-name | |
1649 | @deffnx method slot-missing (class <class>) (object <object>) slot-name | |
1650 | @deffnx method slot-missing (class <class>) (object <object>) slot-name value | |
1651 | When an application attempts to reference or set a class or instance | |
1652 | slot by name, and the slot name is invalid for the specified @var{class} | |
1653 | or @var{object}, GOOPS calls the @code{slot-missing} generic function. | |
1654 | ||
1655 | The default methods all call @code{goops-error} with an appropriate | |
1656 | message. | |
1657 | @end deffn | |
1658 | ||
1659 | @deffn generic slot-unbound | |
1660 | @deffnx method slot-unbound (object <object>) | |
1661 | @deffnx method slot-unbound (class <class>) slot-name | |
1662 | @deffnx method slot-unbound (class <class>) (object <object>) slot-name | |
1663 | When an application attempts to reference a class or instance slot, and | |
1664 | the slot's value is unbound, GOOPS calls the @code{slot-unbound} generic | |
1665 | function. | |
1666 | ||
1667 | The default methods all call @code{goops-error} with an appropriate | |
1668 | message. | |
1669 | @end deffn | |
1670 | ||
62d7cba3 | 1671 | |
12fe9fcf NJ |
1672 | @node GOOPS Error Handling |
1673 | @section Error Handling | |
1674 | ||
1675 | The procedure @code{goops-error} is called to raise an appropriate error | |
1676 | by the default methods of the following generic functions: | |
1677 | ||
1678 | @itemize @bullet | |
1679 | @item | |
1680 | @code{slot-missing} (@pxref{Accessing Slots,, slot-missing}) | |
1681 | ||
1682 | @item | |
1683 | @code{slot-unbound} (@pxref{Accessing Slots,, slot-unbound}) | |
1684 | ||
1685 | @item | |
1686 | @code{no-method} (@pxref{Handling Invocation Errors,, no-method}) | |
1687 | ||
1688 | @item | |
1689 | @code{no-applicable-method} (@pxref{Handling Invocation Errors,, | |
1690 | no-applicable-method}) | |
1691 | ||
1692 | @item | |
1693 | @code{no-next-method} (@pxref{Handling Invocation Errors,, | |
1694 | no-next-method}) | |
1695 | @end itemize | |
1696 | ||
1697 | If you customize these functions for particular classes or metaclasses, | |
1698 | you may still want to use @code{goops-error} to signal any error | |
1699 | conditions that you detect. | |
1700 | ||
df0a1002 | 1701 | @deffn procedure goops-error format-string arg @dots{} |
12fe9fcf | 1702 | Raise an error with key @code{goops-error} and error message constructed |
df0a1002 BT |
1703 | from @var{format-string} and @var{arg} @enddots{}. Error message |
1704 | formatting is as done by @code{scm-error}. | |
12fe9fcf NJ |
1705 | @end deffn |
1706 | ||
1707 | ||
2cb8cf04 NJ |
1708 | @node GOOPS Object Miscellany |
1709 | @section GOOPS Object Miscellany | |
1710 | ||
1711 | Here we cover some points about GOOPS objects that aren't substantial | |
1712 | enough to merit sections on their own. | |
1713 | ||
1714 | @subheading Object Equality | |
1715 | ||
1716 | When GOOPS is loaded, @code{eqv?}, @code{equal?} and @code{=} become | |
1717 | generic functions, and you can define methods for them, specialized for | |
1718 | your own classes, so as to control what the various kinds of equality | |
1719 | mean for your classes. | |
1720 | ||
1721 | For example, the @code{assoc} procedure, for looking up an entry in an | |
1722 | alist, is specified as using @code{equal?} to determine when the car of | |
1723 | an entry in the alist is the same as the key parameter that @code{assoc} | |
1724 | is called with. Hence, if you had defined a new class, and wanted to | |
1725 | use instances of that class as the keys in an alist, you could define a | |
1726 | method for @code{equal?}, for your class, to control @code{assoc}'s | |
1727 | lookup precisely. | |
1728 | ||
1729 | @subheading Cloning Objects | |
1730 | ||
1731 | @deffn generic shallow-clone | |
1732 | @deffnx method shallow-clone (self <object>) | |
1733 | Return a ``shallow'' clone of @var{self}. The default method makes a | |
1734 | shallow clone by allocating a new instance and copying slot values from | |
1735 | self to the new instance. Each slot value is copied either as an | |
1736 | immediate value or by reference. | |
1737 | @end deffn | |
1738 | ||
1739 | @deffn generic deep-clone | |
1740 | @deffnx method deep-clone (self <object>) | |
1741 | Return a ``deep'' clone of @var{self}. The default method makes a deep | |
1742 | clone by allocating a new instance and copying or cloning slot values | |
1743 | from self to the new instance. If a slot value is an instance | |
1744 | (satisfies @code{instance?}), it is cloned by calling @code{deep-clone} | |
1745 | on that value. Other slot values are copied either as immediate values | |
1746 | or by reference. | |
1747 | @end deffn | |
1748 | ||
1749 | @subheading Write and Display | |
1750 | ||
1751 | @deffn {primitive generic} write object port | |
1752 | @deffnx {primitive generic} display object port | |
1753 | When GOOPS is loaded, @code{write} and @code{display} become generic | |
1754 | functions with special methods for printing | |
1755 | ||
1756 | @itemize @bullet | |
1757 | @item | |
1758 | objects - instances of the class @code{<object>} | |
1759 | ||
1760 | @item | |
1761 | foreign objects - instances of the class @code{<foreign-object>} | |
1762 | ||
1763 | @item | |
1764 | classes - instances of the class @code{<class>} | |
1765 | ||
1766 | @item | |
1767 | generic functions - instances of the class @code{<generic>} | |
1768 | ||
1769 | @item | |
1770 | methods - instances of the class @code{<method>}. | |
1771 | @end itemize | |
1772 | ||
1773 | @code{write} and @code{display} print non-GOOPS values in the same way | |
1774 | as the Guile primitive @code{write} and @code{display} functions. | |
1775 | @end deffn | |
1776 | ||
1777 | In addition to the cases mentioned, you can of course define | |
1778 | @code{write} and @code{display} methods for your own classes, to | |
e888334c | 1779 | customize how instances of those classes are printed. |
2cb8cf04 NJ |
1780 | |
1781 | ||
a9bf12c2 NJ |
1782 | @node The Metaobject Protocol |
1783 | @section The Metaobject Protocol | |
a0e07ba4 | 1784 | |
0b452f2c NJ |
1785 | At this point, we've said about as much as can be said about GOOPS |
1786 | without having to confront the idea of the metaobject protocol. There | |
1787 | are a couple more topics that could be discussed in isolation first --- | |
1788 | class redefinition, and changing the class of existing instances --- but | |
1789 | in practice developers using them will be advanced enough to want to | |
1790 | understand the metaobject protocol too, and will probably be using the | |
1791 | protocol to customize exactly what happens during these events. | |
1792 | ||
1793 | So let's plunge in. GOOPS is based on a ``metaobject protocol'' (aka | |
1794 | ``MOP'') derived from the ones used in CLOS (the Common Lisp Object | |
1795 | System), tiny-clos (a small Scheme implementation of a subset of CLOS | |
1796 | functionality) and STKlos. | |
a0e07ba4 | 1797 | |
a46f77f9 NJ |
1798 | The MOP underlies many possible GOOPS customizations --- such as |
1799 | defining an @code{initialize} method to customize the initialization of | |
1800 | instances of an application-defined class --- and an understanding of | |
1801 | the MOP makes it much easier to explain such customizations in a precise | |
1802 | way. And at a deeper level, understanding the MOP is a key part of | |
1803 | understanding GOOPS, and of taking full advantage of GOOPS' power, by | |
1804 | customizing the behaviour of GOOPS itself. | |
a0e07ba4 | 1805 | |
a9bf12c2 NJ |
1806 | @menu |
1807 | * Metaobjects and the Metaobject Protocol:: | |
a46f77f9 | 1808 | * Metaclasses:: |
a9bf12c2 | 1809 | * MOP Specification:: |
d9ff8506 | 1810 | * Instance Creation Protocol:: |
a46f77f9 | 1811 | * Class Definition Protocol:: |
58ad1de7 | 1812 | * Customizing Class Definition:: |
a9bf12c2 | 1813 | * Method Definition:: |
de6b3a5c | 1814 | * Method Definition Internals:: |
eed4cc7b | 1815 | * Generic Function Internals:: |
a9bf12c2 NJ |
1816 | * Generic Function Invocation:: |
1817 | @end menu | |
1818 | ||
1819 | @node Metaobjects and the Metaobject Protocol | |
1820 | @subsection Metaobjects and the Metaobject Protocol | |
1821 | ||
5aaf0709 NJ |
1822 | The building blocks of GOOPS are classes, slot definitions, instances, |
1823 | generic functions and methods. A class is a grouping of inheritance | |
1824 | relations and slot definitions. An instance is an object with slots | |
1825 | that are allocated following the rules implied by its class's | |
a9bf12c2 NJ |
1826 | superclasses and slot definitions. A generic function is a collection |
1827 | of methods and rules for determining which of those methods to apply | |
1828 | when the generic function is invoked. A method is a procedure and a set | |
1829 | of specializers that specify the type of arguments to which the | |
1830 | procedure is applicable. | |
1831 | ||
1832 | Of these entities, GOOPS represents classes, generic functions and | |
1833 | methods as ``metaobjects''. In other words, the values in a GOOPS | |
1834 | program that describe classes, generic functions and methods, are | |
1835 | themselves instances (or ``objects'') of special GOOPS classes that | |
1836 | encapsulate the behaviour, respectively, of classes, generic functions, | |
1837 | and methods. | |
1838 | ||
1839 | (The other two entities are slot definitions and instances. Slot | |
1840 | definitions are not strictly instances, but every slot definition is | |
1841 | associated with a GOOPS class that specifies the behaviour of the slot | |
1842 | as regards accessibility and protection from garbage collection. | |
1843 | Instances are of course objects in the usual sense, and there is no | |
1844 | benefit from thinking of them as metaobjects.) | |
1845 | ||
a46f77f9 | 1846 | The ``metaobject protocol'' (or ``MOP'') is the specification of the |
a9bf12c2 NJ |
1847 | generic functions which determine the behaviour of these metaobjects and |
1848 | the circumstances in which these generic functions are invoked. | |
1849 | ||
1850 | For a concrete example of what this means, consider how GOOPS calculates | |
1851 | the set of slots for a class that is being defined using | |
1852 | @code{define-class}. The desired set of slots is the union of the new | |
1853 | class's direct slots and the slots of all its superclasses. But | |
1854 | @code{define-class} itself does not perform this calculation. Instead, | |
1855 | there is a method of the @code{initialize} generic function that is | |
1856 | specialized for instances of type @code{<class>}, and it is this method | |
1857 | that performs the slot calculation. | |
1858 | ||
1859 | @code{initialize} is a generic function which GOOPS calls whenever a new | |
1860 | instance is created, immediately after allocating memory for a new | |
1861 | instance, in order to initialize the new instance's slots. The sequence | |
1862 | of steps is as follows. | |
1863 | ||
1864 | @itemize @bullet | |
1865 | @item | |
1866 | @code{define-class} uses @code{make} to make a new instance of the | |
5aaf0709 NJ |
1867 | @code{<class>} class, passing as initialization arguments the |
1868 | superclasses, slot definitions and class options that were specified in | |
1869 | the @code{define-class} form. | |
a9bf12c2 NJ |
1870 | |
1871 | @item | |
a46f77f9 | 1872 | @code{make} allocates memory for the new instance, and invokes the |
a9bf12c2 NJ |
1873 | @code{initialize} generic function to initialize the new instance's |
1874 | slots. | |
1875 | ||
1876 | @item | |
1877 | The @code{initialize} generic function applies the method that is | |
1878 | specialized for instances of type @code{<class>}, and this method | |
1879 | performs the slot calculation. | |
1880 | @end itemize | |
1881 | ||
1882 | In other words, rather than being hardcoded in @code{define-class}, the | |
a46f77f9 NJ |
1883 | default behaviour of class definition is encapsulated by generic |
1884 | function methods that are specialized for the class @code{<class>}. | |
a9bf12c2 NJ |
1885 | |
1886 | It is possible to create a new class that inherits from @code{<class>}, | |
1887 | which is called a ``metaclass'', and to write a new @code{initialize} | |
1888 | method that is specialized for instances of the new metaclass. Then, if | |
1889 | the @code{define-class} form includes a @code{#:metaclass} class option | |
1890 | whose value is the new metaclass, the class that is defined by the | |
1891 | @code{define-class} form will be an instance of the new metaclass rather | |
1892 | than of the default @code{<class>}, and will be defined in accordance | |
1893 | with the new @code{initialize} method. Thus the default slot | |
1894 | calculation, as well as any other aspect of the new class's relationship | |
1895 | with its superclasses, can be modified or overridden. | |
1896 | ||
1897 | In a similar way, the behaviour of generic functions can be modified or | |
1898 | overridden by creating a new class that inherits from the standard | |
1899 | generic function class @code{<generic>}, writing appropriate methods | |
1900 | that are specialized to the new class, and creating new generic | |
1901 | functions that are instances of the new class. | |
1902 | ||
1903 | The same is true for method metaobjects. And the same basic mechanism | |
1904 | allows the application class author to write an @code{initialize} method | |
1905 | that is specialized to their application class, to initialize instances | |
1906 | of that class. | |
1907 | ||
1908 | Such is the power of the MOP. Note that @code{initialize} is just one | |
1909 | of a large number of generic functions that can be customized to modify | |
1910 | the behaviour of application objects and classes and of GOOPS itself. | |
5aaf0709 NJ |
1911 | Each following section covers a particular area of GOOPS functionality, |
1912 | and describes the generic functions that are relevant for customization | |
1913 | of that area. | |
1914 | ||
a46f77f9 NJ |
1915 | @node Metaclasses |
1916 | @subsection Metaclasses | |
a9bf12c2 NJ |
1917 | |
1918 | A @dfn{metaclass} is the class of an object which represents a GOOPS | |
1919 | class. Put more succinctly, a metaclass is a class's class. | |
1920 | ||
1921 | Most GOOPS classes have the metaclass @code{<class>} and, by default, | |
1922 | any new class that is created using @code{define-class} has the | |
1923 | metaclass @code{<class>}. | |
1924 | ||
1925 | But what does this really mean? To find out, let's look in more detail | |
1926 | at what happens when a new class is created using @code{define-class}: | |
1927 | ||
1928 | @example | |
1929 | (define-class <my-class> (<object>) . slots) | |
1930 | @end example | |
1931 | ||
a46f77f9 NJ |
1932 | @noindent |
1933 | Guile expands this to something like: | |
a9bf12c2 NJ |
1934 | |
1935 | @example | |
1936 | (define <my-class> (class (<object>) . slots)) | |
1937 | @end example | |
1938 | ||
a46f77f9 NJ |
1939 | @noindent |
1940 | which in turn expands to: | |
a9bf12c2 NJ |
1941 | |
1942 | @example | |
1943 | (define <my-class> | |
7cfcb60b | 1944 | (make <class> #:dsupers (list <object>) #:slots slots)) |
a9bf12c2 NJ |
1945 | @end example |
1946 | ||
a46f77f9 NJ |
1947 | As this expansion makes clear, the resulting value of @code{<my-class>} |
1948 | is an instance of the class @code{<class>} with slot values specifying | |
1949 | the superclasses and slot definitions for the class @code{<my-class>}. | |
7cfcb60b | 1950 | (@code{#:dsupers} and @code{#:slots} are initialization keywords for the |
a46f77f9 | 1951 | @code{dsupers} and @code{dslots} slots of the @code{<class>} class.) |
a9bf12c2 | 1952 | |
a46f77f9 NJ |
1953 | Now suppose that you want to define a new class with a metaclass other |
1954 | than the default @code{<class>}. This is done by writing: | |
a9bf12c2 NJ |
1955 | |
1956 | @example | |
1957 | (define-class <my-class2> (<object>) | |
1958 | slot @dots{} | |
1959 | #:metaclass <my-metaclass>) | |
1960 | @end example | |
1961 | ||
a46f77f9 NJ |
1962 | @noindent |
1963 | and Guile expands @emph{this} to something like: | |
a9bf12c2 NJ |
1964 | |
1965 | @example | |
1966 | (define <my-class2> | |
7cfcb60b | 1967 | (make <my-metaclass> #:dsupers (list <object>) #:slots slots)) |
a9bf12c2 NJ |
1968 | @end example |
1969 | ||
1970 | In this case, the value of @code{<my-class2>} is an instance of the more | |
1971 | specialized class @code{<my-metaclass>}. Note that | |
1972 | @code{<my-metaclass>} itself must previously have been defined as a | |
1973 | subclass of @code{<class>}. For a full discussion of when and how it is | |
1974 | useful to define new metaclasses, see @ref{MOP Specification}. | |
1975 | ||
1976 | Now let's make an instance of @code{<my-class2>}: | |
1977 | ||
1978 | @example | |
1979 | (define my-object (make <my-class2> ...)) | |
1980 | @end example | |
1981 | ||
1982 | All of the following statements are correct expressions of the | |
1983 | relationships between @code{my-object}, @code{<my-class2>}, | |
1984 | @code{<my-metaclass>} and @code{<class>}. | |
1985 | ||
1986 | @itemize @bullet | |
1987 | @item | |
1988 | @code{my-object} is an instance of the class @code{<my-class2>}. | |
1989 | ||
1990 | @item | |
1991 | @code{<my-class2>} is an instance of the class @code{<my-metaclass>}. | |
1992 | ||
1993 | @item | |
1994 | @code{<my-metaclass>} is an instance of the class @code{<class>}. | |
1995 | ||
1996 | @item | |
1997 | The class of @code{my-object} is @code{<my-class2>}. | |
1998 | ||
a9bf12c2 NJ |
1999 | @item |
2000 | The class of @code{<my-class2>} is @code{<my-metaclass>}. | |
2001 | ||
a9bf12c2 NJ |
2002 | @item |
2003 | The class of @code{<my-metaclass>} is @code{<class>}. | |
a9bf12c2 NJ |
2004 | @end itemize |
2005 | ||
a9bf12c2 NJ |
2006 | |
2007 | @node MOP Specification | |
2008 | @subsection MOP Specification | |
2009 | ||
2010 | The aim of the MOP specification in this chapter is to specify all the | |
2011 | customizable generic function invocations that can be made by the standard | |
2012 | GOOPS syntax, procedures and methods, and to explain the protocol for | |
2013 | customizing such invocations. | |
2014 | ||
a46f77f9 NJ |
2015 | A generic function invocation is customizable if the types of the |
2016 | arguments to which it is applied are not completely determined by the | |
2017 | lexical context in which the invocation appears. For example, the | |
2018 | @code{(initialize @var{instance} @var{initargs})} invocation in the | |
2019 | default @code{make-instance} method is customizable, because the type of | |
2020 | the @code{@var{instance}} argument is determined by the class that was | |
2021 | passed to @code{make-instance}. | |
a0e07ba4 | 2022 | |
a46f77f9 NJ |
2023 | (Whereas --- to give a counter-example --- the @code{(make <generic> |
2024 | #:name ',name)} invocation in @code{define-generic} is not customizable, | |
2025 | because all of its arguments have lexically determined types.) | |
a0e07ba4 NJ |
2026 | |
2027 | When using this rule to decide whether a given generic function invocation | |
2028 | is customizable, we ignore arguments that are expected to be handled in | |
2029 | method definitions as a single ``rest'' list argument. | |
2030 | ||
2031 | For each customizable generic function invocation, the @dfn{invocation | |
2032 | protocol} is explained by specifying | |
2033 | ||
2034 | @itemize @bullet | |
2035 | @item | |
2036 | what, conceptually, the applied method is intended to do | |
2037 | ||
2038 | @item | |
2039 | what assumptions, if any, the caller makes about the applied method's side | |
2040 | effects | |
2041 | ||
2042 | @item | |
2043 | what the caller expects to get as the applied method's return value. | |
2044 | @end itemize | |
2045 | ||
d9ff8506 NJ |
2046 | |
2047 | @node Instance Creation Protocol | |
2048 | @subsection Instance Creation Protocol | |
2049 | ||
2050 | @code{make <class> . @var{initargs}} (method) | |
2051 | ||
2052 | @itemize @bullet | |
2053 | @item | |
2054 | @code{allocate-instance @var{class} @var{initargs}} (generic) | |
2055 | ||
2056 | The applied @code{allocate-instance} method should allocate storage for | |
2057 | a new instance of class @var{class} and return the uninitialized instance. | |
2058 | ||
2059 | @item | |
2060 | @code{initialize @var{instance} @var{initargs}} (generic) | |
2061 | ||
2062 | @var{instance} is the uninitialized instance returned by | |
2063 | @code{allocate-instance}. The applied method should initialize the new | |
2064 | instance in whatever sense is appropriate for its class. The method's | |
2065 | return value is ignored. | |
2066 | @end itemize | |
2067 | ||
2068 | @code{make} itself is a generic function. Hence the @code{make} | |
2069 | invocation itself can be customized in the case where the new instance's | |
2070 | metaclass is more specialized than the default @code{<class>}, by | |
2071 | defining a @code{make} method that is specialized to that metaclass. | |
2072 | ||
2073 | Normally, however, the method for classes with metaclass @code{<class>} | |
2074 | will be applied. This method calls two generic functions: | |
2075 | ||
2076 | @itemize @bullet | |
2077 | @item | |
2078 | (allocate-instance @var{class} . @var{initargs}) | |
2079 | ||
2080 | @item | |
2081 | (initialize @var{instance} . @var{initargs}) | |
2082 | @end itemize | |
2083 | ||
2084 | @code{allocate-instance} allocates storage for and returns the new | |
2085 | instance, uninitialized. You might customize @code{allocate-instance}, | |
2086 | for example, if you wanted to provide a GOOPS wrapper around some other | |
2087 | object programming system. | |
2088 | ||
2089 | To do this, you would create a specialized metaclass, which would act as | |
2090 | the metaclass for all classes and instances from the other system. Then | |
2091 | define an @code{allocate-instance} method, specialized to that | |
2092 | metaclass, which calls a Guile primitive C function (or FFI code), which | |
2093 | in turn allocates the new instance using the interface of the other | |
2094 | object system. | |
2095 | ||
2096 | In this case, for a complete system, you would also need to customize a | |
2097 | number of other generic functions like @code{make} and | |
2098 | @code{initialize}, so that GOOPS knows how to make classes from the | |
2099 | other system, access instance slots, and so on. | |
2100 | ||
2101 | @code{initialize} initializes the instance that is returned by | |
2102 | @code{allocate-instance}. The standard GOOPS methods perform | |
2103 | initializations appropriate to the instance class. | |
2104 | ||
2105 | @itemize @bullet | |
2106 | @item | |
2107 | At the least specialized level, the method for instances of type | |
2108 | @code{<object>} performs internal GOOPS instance initialization, and | |
2109 | initializes the instance's slots according to the slot definitions and | |
2110 | any slot initialization keywords that appear in @var{initargs}. | |
2111 | ||
2112 | @item | |
2113 | The method for instances of type @code{<class>} calls | |
2114 | @code{(next-method)}, then performs the class initializations described | |
2115 | in @ref{Class Definition Protocol}. | |
2116 | ||
2117 | @item | |
2118 | and so on for generic functions, methods, operator classes @dots{} | |
2119 | @end itemize | |
2120 | ||
2121 | Similarly, you can customize the initialization of instances of any | |
2122 | application-defined class by defining an @code{initialize} method | |
2123 | specialized to that class. | |
2124 | ||
2125 | Imagine a class whose instances' slots need to be initialized at | |
2126 | instance creation time by querying a database. Although it might be | |
2127 | possible to achieve this a combination of @code{#:init-thunk} keywords | |
2128 | and closures in the slot definitions, it may be neater to write an | |
2129 | @code{initialize} method for the class that queries the database once | |
2130 | and initializes all the dependent slot values according to the results. | |
2131 | ||
2132 | ||
a46f77f9 NJ |
2133 | @node Class Definition Protocol |
2134 | @subsection Class Definition Protocol | |
a0e07ba4 | 2135 | |
476a51eb NJ |
2136 | Here is a summary diagram of the syntax, procedures and generic |
2137 | functions that may be involved in class definition. | |
2138 | ||
2139 | @noindent | |
2140 | @code{define-class} (syntax) | |
2141 | ||
2142 | @itemize @bullet | |
2143 | @item | |
2144 | @code{class} (syntax) | |
2145 | ||
2146 | @itemize @bullet | |
2147 | @item | |
2148 | @code{make-class} (procedure) | |
2149 | ||
2150 | @itemize @bullet | |
2151 | @item | |
2152 | @code{ensure-metaclass} (procedure) | |
2153 | ||
476a51eb NJ |
2154 | @item |
2155 | @code{make @var{metaclass} @dots{}} (generic) | |
2156 | ||
2157 | @itemize @bullet | |
2158 | @item | |
2159 | @code{allocate-instance} (generic) | |
2160 | ||
2161 | @item | |
2162 | @code{initialize} (generic) | |
2163 | ||
2164 | @itemize @bullet | |
2165 | @item | |
2166 | @code{compute-cpl} (generic) | |
2167 | ||
2168 | @itemize @bullet | |
2169 | @item | |
2170 | @code{compute-std-cpl} (procedure) | |
2171 | @end itemize | |
2172 | ||
2173 | @item | |
2174 | @code{compute-slots} (generic) | |
2175 | ||
2176 | @item | |
2177 | @code{compute-get-n-set} (generic) | |
2178 | ||
2179 | @item | |
2180 | @code{compute-getter-method} (generic) | |
2181 | ||
2182 | @item | |
2183 | @code{compute-setter-method} (generic) | |
2184 | @end itemize | |
2185 | @end itemize | |
2186 | @end itemize | |
2187 | @end itemize | |
2188 | ||
2189 | @item | |
2190 | @code{class-redefinition} (generic) | |
2191 | ||
2192 | @itemize @bullet | |
2193 | @item | |
2194 | @code{remove-class-accessors} (generic) | |
2195 | ||
2196 | @item | |
2197 | @code{update-direct-method!} (generic) | |
2198 | ||
2199 | @item | |
2200 | @code{update-direct-subclass!} (generic) | |
2201 | @end itemize | |
2202 | @end itemize | |
2203 | ||
2204 | Wherever a step above is marked as ``generic'', it can be customized, | |
2205 | and the detail shown below it is only ``correct'' insofar as it | |
2206 | describes what the default method of that generic function does. For | |
2207 | example, if you write an @code{initialize} method, for some metaclass, | |
2208 | that does not call @code{next-method} and does not call | |
2209 | @code{compute-cpl}, then @code{compute-cpl} will not be called when a | |
2210 | class is defined with that metaclass. | |
2211 | ||
d9ff8506 NJ |
2212 | A @code{(define-class ...)} form (@pxref{Class Definition}) expands to |
2213 | an expression which | |
58ad1de7 NJ |
2214 | |
2215 | @itemize @bullet | |
2216 | @item | |
2217 | checks that it is being evaluated only at top level | |
2218 | ||
2219 | @item | |
2220 | defines any accessors that are implied by the @var{slot-definition}s | |
2221 | ||
2222 | @item | |
d9ff8506 | 2223 | uses @code{class} to create the new class |
58ad1de7 NJ |
2224 | |
2225 | @item | |
2226 | checks for a previous class definition for @var{name} and, if found, | |
2227 | handles the redefinition by invoking @code{class-redefinition} | |
2228 | (@pxref{Redefining a Class}). | |
2229 | @end itemize | |
2230 | ||
df0a1002 BT |
2231 | @deffn syntax class name (super @dots{}) @ |
2232 | slot-definition @dots{} class-option @dots{} | |
58ad1de7 | 2233 | Return a newly created class that inherits from @var{super}s, with |
df0a1002 BT |
2234 | direct slots defined by @var{slot-definition}s and @var{class-option}s. |
2235 | For the format of @var{slot-definition}s and @var{class-option}s, see | |
2236 | @ref{Class Definition,, define-class}. | |
58ad1de7 NJ |
2237 | @end deffn |
2238 | ||
2239 | @noindent @code{class} expands to an expression which | |
2240 | ||
2241 | @itemize @bullet | |
2242 | @item | |
2243 | processes the class and slot definition options to check that they are | |
2244 | well-formed, to convert the @code{#:init-form} option to an | |
2245 | @code{#:init-thunk} option, to supply a default environment parameter | |
2246 | (the current top-level environment) and to evaluate all the bits that | |
2247 | need to be evaluated | |
2248 | ||
2249 | @item | |
2250 | calls @code{make-class} to create the class with the processed and | |
2251 | evaluated parameters. | |
2252 | @end itemize | |
2253 | ||
df0a1002 | 2254 | @deffn procedure make-class supers slots class-option @dots{} |
58ad1de7 | 2255 | Return a newly created class that inherits from @var{supers}, with |
df0a1002 BT |
2256 | direct slots defined by @var{slots} and @var{class-option}s. For the |
2257 | format of @var{slots} and @var{class-option}s, see @ref{Class | |
f60a8353 | 2258 | Definition,, define-class}, except note that for @code{make-class}, |
df0a1002 | 2259 | @var{slots} is a separate list of slot definitions. |
58ad1de7 NJ |
2260 | @end deffn |
2261 | ||
2262 | @noindent @code{make-class} | |
2263 | ||
2264 | @itemize @bullet | |
2265 | @item | |
2266 | adds @code{<object>} to the @var{supers} list if @var{supers} is empty | |
2267 | or if none of the classes in @var{supers} have @code{<object>} in their | |
2268 | class precedence list | |
2269 | ||
2270 | @item | |
2271 | defaults the @code{#:environment}, @code{#:name} and @code{#:metaclass} | |
2272 | options, if they are not specified by @var{options}, to the current | |
2273 | top-level environment, the unbound value, and @code{(ensure-metaclass | |
d9ff8506 | 2274 | @var{supers})} respectively |
58ad1de7 NJ |
2275 | |
2276 | @item | |
2277 | checks for duplicate classes in @var{supers} and duplicate slot names in | |
2278 | @var{slots}, and signals an error if there are any duplicates | |
2279 | ||
2280 | @item | |
2281 | calls @code{make}, passing the metaclass as the first parameter and all | |
2282 | other parameters as option keywords with values. | |
2283 | @end itemize | |
2284 | ||
2285 | @deffn procedure ensure-metaclass supers env | |
2286 | Return a metaclass suitable for a class that inherits from the list of | |
2287 | classes in @var{supers}. The returned metaclass is the union by | |
2288 | inheritance of the metaclasses of the classes in @var{supers}. | |
2289 | ||
2290 | In the simplest case, where all the @var{supers} are straightforward | |
2291 | classes with metaclass @code{<class>}, the returned metaclass is just | |
2292 | @code{<class>}. | |
2293 | ||
2294 | For a more complex example, suppose that @var{supers} contained one | |
2295 | class with metaclass @code{<operator-class>} and one with metaclass | |
2296 | @code{<foreign-object-class>}. Then the returned metaclass would be a | |
2297 | class that inherits from both @code{<operator-class>} and | |
2298 | @code{<foreign-object-class>}. | |
2299 | ||
2300 | If @var{supers} is the empty list, @code{ensure-metaclass} returns the | |
2301 | default GOOPS metaclass @code{<class>}. | |
2302 | ||
2303 | GOOPS keeps a list of the metaclasses created by | |
2304 | @code{ensure-metaclass}, so that each required type of metaclass only | |
2305 | has to be created once. | |
2306 | ||
2307 | The @code{env} parameter is ignored. | |
2308 | @end deffn | |
2309 | ||
df0a1002 | 2310 | @deffn generic make metaclass initarg @dots{} |
d9ff8506 NJ |
2311 | @var{metaclass} is the metaclass of the class being defined, either |
2312 | taken from the @code{#:metaclass} class option or computed by | |
2313 | @code{ensure-metaclass}. The applied method must create and return the | |
2314 | fully initialized class metaobject for the new class definition. | |
58ad1de7 NJ |
2315 | @end deffn |
2316 | ||
df0a1002 BT |
2317 | The @code{(make @var{metaclass} @var{initarg} @dots{})} invocation is a |
2318 | particular case of the instance creation protocol covered in the | |
2319 | previous section. It will create an class metaobject with metaclass | |
2320 | @var{metaclass}. By default, this metaobject will be initialized by the | |
2321 | @code{initialize} method that is specialized for instances of type | |
2322 | @code{<class>}. | |
58ad1de7 | 2323 | |
d9ff8506 NJ |
2324 | The @code{initialize} method for classes (signature @code{(initialize |
2325 | <class> initargs)}) calls the following generic functions. | |
58ad1de7 NJ |
2326 | |
2327 | @itemize @bullet | |
2328 | @item | |
d9ff8506 | 2329 | @code{compute-cpl @var{class}} (generic) |
58ad1de7 | 2330 | |
d9ff8506 NJ |
2331 | The applied method should compute and return the class precedence list |
2332 | for @var{class} as a list of class metaobjects. When @code{compute-cpl} | |
2333 | is called, the following @var{class} metaobject slots have all been | |
2334 | initialized: @code{name}, @code{direct-supers}, @code{direct-slots}, | |
2335 | @code{direct-subclasses} (empty), @code{direct-methods}. The value | |
2336 | returned by @code{compute-cpl} will be stored in the @code{cpl} slot. | |
58ad1de7 | 2337 | |
58ad1de7 | 2338 | @item |
d9ff8506 | 2339 | @code{compute-slots @var{class}} (generic) |
58ad1de7 | 2340 | |
d9ff8506 NJ |
2341 | The applied method should compute and return the slots (union of direct |
2342 | and inherited) for @var{class} as a list of slot definitions. When | |
2343 | @code{compute-slots} is called, all the @var{class} metaobject slots | |
2344 | mentioned for @code{compute-cpl} have been initialized, plus the | |
2345 | following: @code{cpl}, @code{redefined} (@code{#f}), @code{environment}. | |
2346 | The value returned by @code{compute-slots} will be stored in the | |
2347 | @code{slots} slot. | |
58ad1de7 NJ |
2348 | |
2349 | @item | |
d9ff8506 NJ |
2350 | @code{compute-get-n-set @var{class} @var{slot-def}} (generic) |
2351 | ||
2352 | @code{initialize} calls @code{compute-get-n-set} for each slot computed | |
2353 | by @code{compute-slots}. The applied method should compute and return a | |
2354 | pair of closures that, respectively, get and set the value of the specified | |
2355 | slot. The get closure should have arity 1 and expect a single argument | |
2356 | that is the instance whose slot value is to be retrieved. The set closure | |
2357 | should have arity 2 and expect two arguments, where the first argument is | |
2358 | the instance whose slot value is to be set and the second argument is the | |
2359 | new value for that slot. The closures should be returned in a two element | |
2360 | list: @code{(list @var{get} @var{set})}. | |
2361 | ||
2362 | The closures returned by @code{compute-get-n-set} are stored as part of | |
2363 | the value of the @var{class} metaobject's @code{getters-n-setters} slot. | |
2364 | Specifically, the value of this slot is a list with the same number of | |
2365 | elements as there are slots in the class, and each element looks either like | |
2366 | ||
2367 | @example | |
2368 | @code{(@var{slot-name-symbol} @var{init-function} . @var{index})} | |
2369 | @end example | |
2370 | ||
2371 | or like | |
2372 | ||
2373 | @example | |
2374 | @code{(@var{slot-name-symbol} @var{init-function} @var{get} @var{set})} | |
2375 | @end example | |
2376 | ||
2377 | Where the get and set closures are replaced by @var{index}, the slot is | |
2378 | an instance slot and @var{index} is the slot's index in the underlying | |
2379 | structure: GOOPS knows how to get and set the value of such slots and so | |
2380 | does not need specially constructed get and set closures. Otherwise, | |
2381 | @var{get} and @var{set} are the closures returned by @code{compute-get-n-set}. | |
2382 | ||
2383 | The structure of the @code{getters-n-setters} slot value is important when | |
2384 | understanding the next customizable generic functions that @code{initialize} | |
2385 | calls@dots{} | |
58ad1de7 NJ |
2386 | |
2387 | @item | |
d9ff8506 NJ |
2388 | @code{compute-getter-method @var{class} @var{gns}} (generic) |
2389 | ||
27643d70 NJ |
2390 | @code{initialize} calls @code{compute-getter-method} for each of the |
2391 | class's slots (as determined by @code{compute-slots}) that includes a | |
d9ff8506 | 2392 | @code{#:getter} or @code{#:accessor} slot option. @var{gns} is the |
27643d70 NJ |
2393 | element of the @var{class} metaobject's @code{getters-n-setters} slot |
2394 | that specifies how the slot in question is referenced and set, as | |
2395 | described above under @code{compute-get-n-set}. The applied method | |
2396 | should create and return a method that is specialized for instances of | |
2397 | type @var{class} and uses the get closure to retrieve the slot's value. | |
d9ff8506 NJ |
2398 | @code{initialize} uses @code{add-method!} to add the returned method to |
2399 | the generic function named by the slot definition's @code{#:getter} or | |
2400 | @code{#:accessor} option. | |
58ad1de7 NJ |
2401 | |
2402 | @item | |
d9ff8506 NJ |
2403 | @code{compute-setter-method @var{class} @var{gns}} (generic) |
2404 | ||
2405 | @code{compute-setter-method} is invoked with the same arguments as | |
2406 | @code{compute-getter-method}, for each of the class's slots that includes | |
2407 | a @code{#:setter} or @code{#:accessor} slot option. The applied method | |
2408 | should create and return a method that is specialized for instances of | |
2409 | type @var{class} and uses the set closure to set the slot's value. | |
2410 | @code{initialize} then uses @code{add-method!} to add the returned method | |
2411 | to the generic function named by the slot definition's @code{#:setter} | |
2412 | or @code{#:accessor} option. | |
58ad1de7 NJ |
2413 | @end itemize |
2414 | ||
d9ff8506 NJ |
2415 | @node Customizing Class Definition |
2416 | @subsection Customizing Class Definition | |
2417 | ||
58ad1de7 NJ |
2418 | If the metaclass of the new class is something more specialized than the |
2419 | default @code{<class>}, then the type of @var{class} in the calls above | |
2420 | is more specialized than @code{<class>}, and hence it becomes possible | |
2421 | to define generic function methods, specialized for the new class's | |
2422 | metaclass, that can modify or override the default behaviour of | |
2423 | @code{initialize}, @code{compute-cpl} or @code{compute-get-n-set}. | |
2424 | ||
2425 | @code{compute-cpl} computes the class precedence list (``CPL'') for the | |
68f4fee1 | 2426 | new class (@pxref{Class Precedence List}), and returns it as a list of |
58ad1de7 NJ |
2427 | class objects. The CPL is important because it defines a superclass |
2428 | ordering that is used, when a generic function is invoked upon an | |
2429 | instance of the class, to decide which of the available generic function | |
2430 | methods is the most specific. Hence @code{compute-cpl} could be | |
2431 | customized in order to modify the CPL ordering algorithm for all classes | |
2432 | with a special metaclass. | |
2433 | ||
2434 | The default CPL algorithm is encapsulated by the @code{compute-std-cpl} | |
d9ff8506 | 2435 | procedure, which is called by the default @code{compute-cpl} method. |
58ad1de7 NJ |
2436 | |
2437 | @deffn procedure compute-std-cpl class | |
2438 | Compute and return the class precedence list for @var{class} according | |
68f4fee1 | 2439 | to the algorithm described in @ref{Class Precedence List}. |
58ad1de7 NJ |
2440 | @end deffn |
2441 | ||
2442 | @code{compute-slots} computes and returns a list of all slot definitions | |
2443 | for the new class. By default, this list includes the direct slot | |
2444 | definitions from the @code{define-class} form, plus the slot definitions | |
2445 | that are inherited from the new class's superclasses. The default | |
2446 | @code{compute-slots} method uses the CPL computed by @code{compute-cpl} | |
2447 | to calculate this union of slot definitions, with the rule that slots | |
2448 | inherited from superclasses are shadowed by direct slots with the same | |
2449 | name. One possible reason for customizing @code{compute-slots} would be | |
2450 | to implement an alternative resolution strategy for slot name conflicts. | |
2451 | ||
2452 | @code{compute-get-n-set} computes the low-level closures that will be | |
2453 | used to get and set the value of a particular slot, and returns them in | |
2454 | a list with two elements. | |
2455 | ||
2456 | The closures returned depend on how storage for that slot is allocated. | |
2457 | The standard @code{compute-get-n-set} method, specialized for classes of | |
2458 | type @code{<class>}, handles the standard GOOPS values for the | |
2459 | @code{#:allocation} slot option (@pxref{Slot Options,, allocation}). By | |
2460 | defining a new @code{compute-get-n-set} method for a more specialized | |
2461 | metaclass, it is possible to support new types of slot allocation. | |
2462 | ||
2463 | Suppose you wanted to create a large number of instances of some class | |
2464 | with a slot that should be shared between some but not all instances of | |
2465 | that class - say every 10 instances should share the same slot storage. | |
2466 | The following example shows how to implement and use a new type of slot | |
2467 | allocation to do this. | |
2468 | ||
2469 | @example | |
2470 | (define-class <batched-allocation-metaclass> (<class>)) | |
2471 | ||
2472 | (let ((batch-allocation-count 0) | |
2473 | (batch-get-n-set #f)) | |
2474 | (define-method (compute-get-n-set | |
2475 | (class <batched-allocation-metaclass>) s) | |
2476 | (case (slot-definition-allocation s) | |
2477 | ((#:batched) | |
2478 | ;; If we've already used the same slot storage for 10 instances, | |
2479 | ;; reset variables. | |
2480 | (if (= batch-allocation-count 10) | |
2481 | (begin | |
2482 | (set! batch-allocation-count 0) | |
2483 | (set! batch-get-n-set #f))) | |
2484 | ;; If we don't have a current pair of get and set closures, | |
2485 | ;; create one. make-closure-variable returns a pair of closures | |
2486 | ;; around a single Scheme variable - see goops.scm for details. | |
2487 | (or batch-get-n-set | |
2488 | (set! batch-get-n-set (make-closure-variable))) | |
2489 | ;; Increment the batch allocation count. | |
2490 | (set! batch-allocation-count (+ batch-allocation-count 1)) | |
2491 | batch-get-n-set) | |
2492 | ||
2493 | ;; Call next-method to handle standard allocation types. | |
2494 | (else (next-method))))) | |
2495 | ||
2496 | (define-class <class-using-batched-slot> () | |
2497 | ... | |
2498 | (c #:allocation #:batched) | |
2499 | ... | |
2500 | #:metaclass <batched-allocation-metaclass>) | |
2501 | @end example | |
2502 | ||
2503 | The usage of @code{compute-getter-method} and @code{compute-setter-method} | |
d9ff8506 | 2504 | is described in @ref{Class Definition Protocol}. |
58ad1de7 NJ |
2505 | |
2506 | @code{compute-cpl} and @code{compute-get-n-set} are called by the | |
2507 | standard @code{initialize} method for classes whose metaclass is | |
2508 | @code{<class>}. But @code{initialize} itself can also be modified, by | |
2509 | defining an @code{initialize} method specialized to the new class's | |
2510 | metaclass. Such a method could complete override the standard | |
2511 | behaviour, by not calling @code{(next-method)} at all, but more | |
2512 | typically it would perform additional class initialization steps before | |
2513 | and/or after calling @code{(next-method)} for the standard behaviour. | |
2514 | ||
9e57815d | 2515 | |
a0e07ba4 | 2516 | @node Method Definition |
eb12b401 | 2517 | @subsection Method Definition |
a0e07ba4 NJ |
2518 | |
2519 | @code{define-method} (syntax) | |
2520 | ||
2521 | @itemize @bullet | |
2522 | @item | |
2523 | @code{add-method! @var{target} @var{method}} (generic) | |
bba1a2c7 | 2524 | @end itemize |
a0e07ba4 | 2525 | |
bba1a2c7 | 2526 | @noindent |
a0e07ba4 NJ |
2527 | @code{define-method} invokes the @code{add-method!} generic function to |
2528 | handle adding the new method to a variety of possible targets. GOOPS | |
2529 | includes methods to handle @var{target} as | |
2530 | ||
2531 | @itemize @bullet | |
2532 | @item | |
2533 | a generic function (the most common case) | |
2534 | ||
2535 | @item | |
2536 | a procedure | |
2537 | ||
2538 | @item | |
eed4cc7b | 2539 | a primitive generic (@pxref{Extending Primitives}) |
a0e07ba4 NJ |
2540 | @end itemize |
2541 | ||
2542 | By defining further methods for @code{add-method!}, you can | |
2543 | theoretically handle adding methods to further types of target. | |
bba1a2c7 | 2544 | |
a0e07ba4 | 2545 | |
de6b3a5c NJ |
2546 | @node Method Definition Internals |
2547 | @subsection Method Definition Internals | |
2548 | ||
bba1a2c7 | 2549 | @code{define-method}: |
de6b3a5c NJ |
2550 | |
2551 | @itemize @bullet | |
2552 | @item | |
2553 | checks the form of the first parameter, and applies the following steps | |
2554 | to the accessor's setter if it has the @code{(setter @dots{})} form | |
2555 | ||
2556 | @item | |
2557 | interpolates a call to @code{define-generic} or @code{define-accessor} | |
2558 | if a generic function is not already defined with the supplied name | |
2559 | ||
2560 | @item | |
2561 | calls @code{method} with the @var{parameter}s and @var{body}, to make a | |
2562 | new method instance | |
2563 | ||
2564 | @item | |
2565 | calls @code{add-method!} to add this method to the relevant generic | |
2566 | function. | |
2567 | @end itemize | |
2568 | ||
df0a1002 | 2569 | @deffn syntax method (parameter @dots{}) body @dots{} |
de6b3a5c NJ |
2570 | Make a method whose specializers are defined by the classes in |
2571 | @var{parameter}s and whose procedure definition is constructed from the | |
2572 | @var{parameter} symbols and @var{body} forms. | |
2573 | ||
2574 | The @var{parameter} and @var{body} parameters should be as for | |
68f4fee1 | 2575 | @code{define-method} (@pxref{Methods and Generic Functions,, |
de6b3a5c NJ |
2576 | define-method}). |
2577 | @end deffn | |
2578 | ||
bba1a2c7 NJ |
2579 | @noindent |
2580 | @code{method}: | |
de6b3a5c NJ |
2581 | |
2582 | @itemize @bullet | |
2583 | @item | |
2584 | extracts formals and specializing classes from the @var{parameter}s, | |
2585 | defaulting the class for unspecialized parameters to @code{<top>} | |
2586 | ||
2587 | @item | |
2588 | creates a closure using the formals and the @var{body} forms | |
2589 | ||
2590 | @item | |
2591 | calls @code{make} with metaclass @code{<method>} and the specializers | |
2592 | and closure using the @code{#:specializers} and @code{#:procedure} | |
2593 | keywords. | |
2594 | @end itemize | |
2595 | ||
2596 | @deffn procedure make-method specializers procedure | |
2597 | Make a method using @var{specializers} and @var{procedure}. | |
2598 | ||
2599 | @var{specializers} should be a list of classes that specifies the | |
2600 | parameter combinations to which this method will be applicable. | |
2601 | ||
2602 | @var{procedure} should be the closure that will applied to the generic | |
2603 | function parameters when this method is invoked. | |
2604 | @end deffn | |
2605 | ||
bba1a2c7 | 2606 | @noindent |
de6b3a5c NJ |
2607 | @code{make-method} is a simple wrapper around @code{make} with metaclass |
2608 | @code{<method>}. | |
2609 | ||
2610 | @deffn generic add-method! target method | |
2611 | Generic function for adding method @var{method} to @var{target}. | |
2612 | @end deffn | |
2613 | ||
2614 | @deffn method add-method! (generic <generic>) (method <method>) | |
2615 | Add method @var{method} to the generic function @var{generic}. | |
2616 | @end deffn | |
2617 | ||
2618 | @deffn method add-method! (proc <procedure>) (method <method>) | |
2619 | If @var{proc} is a procedure with generic capability (@pxref{Extending | |
2620 | Primitives,, generic-capability?}), upgrade it to a primitive generic | |
2621 | and add @var{method} to its generic function definition. | |
2622 | @end deffn | |
2623 | ||
2624 | @deffn method add-method! (pg <primitive-generic>) (method <method>) | |
2625 | Add method @var{method} to the generic function definition of @var{pg}. | |
2626 | ||
2627 | Implementation: @code{(add-method! (primitive-generic-generic pg) method)}. | |
2628 | @end deffn | |
2629 | ||
2630 | @deffn method add-method! (whatever <top>) (method <method>) | |
2631 | Raise an error indicating that @var{whatever} is not a valid generic | |
2632 | function. | |
2633 | @end deffn | |
2634 | ||
eed4cc7b NJ |
2635 | @node Generic Function Internals |
2636 | @subsection Generic Function Internals | |
2637 | ||
2638 | @code{define-generic} calls @code{ensure-generic} to upgrade a | |
2639 | pre-existing procedure value, or @code{make} with metaclass | |
2640 | @code{<generic>} to create a new generic function. | |
2641 | ||
2642 | @code{define-accessor} calls @code{ensure-accessor} to upgrade a | |
2643 | pre-existing procedure value, or @code{make-accessor} to create a new | |
2644 | accessor. | |
2645 | ||
2646 | @deffn procedure ensure-generic old-definition [name] | |
2647 | Return a generic function with name @var{name}, if possible by using or | |
2648 | upgrading @var{old-definition}. If unspecified, @var{name} defaults to | |
2649 | @code{#f}. | |
2650 | ||
2651 | If @var{old-definition} is already a generic function, it is returned | |
2652 | unchanged. | |
2653 | ||
2654 | If @var{old-definition} is a Scheme procedure or procedure-with-setter, | |
2655 | @code{ensure-generic} returns a new generic function that uses | |
2656 | @var{old-definition} for its default procedure and setter. | |
2657 | ||
2658 | Otherwise @code{ensure-generic} returns a new generic function with no | |
2659 | defaults and no methods. | |
2660 | @end deffn | |
2661 | ||
2662 | @deffn procedure make-generic [name] | |
2663 | Return a new generic function with name @code{(car @var{name})}. If | |
2664 | unspecified, @var{name} defaults to @code{#f}. | |
2665 | @end deffn | |
2666 | ||
2667 | @code{ensure-generic} calls @code{make} with metaclasses | |
2668 | @code{<generic>} and @code{<generic-with-setter>}, depending on the | |
2669 | previous value of the variable that it is trying to upgrade. | |
2670 | ||
2671 | @code{make-generic} is a simple wrapper for @code{make} with metaclass | |
2672 | @code{<generic>}. | |
2673 | ||
2674 | @deffn procedure ensure-accessor proc [name] | |
2675 | Return an accessor with name @var{name}, if possible by using or | |
2676 | upgrading @var{proc}. If unspecified, @var{name} defaults to @code{#f}. | |
2677 | ||
2678 | If @var{proc} is already an accessor, it is returned unchanged. | |
2679 | ||
2680 | If @var{proc} is a Scheme procedure, procedure-with-setter or generic | |
2681 | function, @code{ensure-accessor} returns an accessor that reuses the | |
2682 | reusable elements of @var{proc}. | |
2683 | ||
2684 | Otherwise @code{ensure-accessor} returns a new accessor with no defaults | |
2685 | and no methods. | |
2686 | @end deffn | |
2687 | ||
2688 | @deffn procedure make-accessor [name] | |
2689 | Return a new accessor with name @code{(car @var{name})}. If | |
2690 | unspecified, @var{name} defaults to @code{#f}. | |
2691 | @end deffn | |
2692 | ||
2693 | @code{ensure-accessor} calls @code{make} with | |
2694 | metaclass @code{<generic-with-setter>}, as well as calls to | |
2695 | @code{ensure-generic}, @code{make-accessor} and (tail recursively) | |
2696 | @code{ensure-accessor}. | |
2697 | ||
2698 | @code{make-accessor} calls @code{make} twice, first | |
2699 | with metaclass @code{<generic>} to create a generic function for the | |
2700 | setter, then with metaclass @code{<generic-with-setter>} to create the | |
2701 | accessor, passing the setter generic function as the value of the | |
2702 | @code{#:setter} keyword. | |
2703 | ||
a0e07ba4 | 2704 | @node Generic Function Invocation |
eb12b401 | 2705 | @subsection Generic Function Invocation |
a0e07ba4 | 2706 | |
bba1a2c7 NJ |
2707 | There is a detailed and customizable protocol involved in the process of |
2708 | invoking a generic function --- i.e., in the process of deciding which | |
2709 | of the generic function's methods are applicable to the current | |
2710 | arguments, and which one of those to apply. Here is a summary diagram | |
2711 | of the generic functions involved. | |
a0e07ba4 | 2712 | |
bba1a2c7 NJ |
2713 | @noindent |
2714 | @code{apply-generic} (generic) | |
a0e07ba4 NJ |
2715 | |
2716 | @itemize @bullet | |
2717 | @item | |
bba1a2c7 | 2718 | @code{no-method} (generic) |
a0e07ba4 NJ |
2719 | |
2720 | @item | |
bba1a2c7 | 2721 | @code{compute-applicable-methods} (generic) |
a0e07ba4 NJ |
2722 | |
2723 | @item | |
bba1a2c7 | 2724 | @code{sort-applicable-methods} (generic) |
a0e07ba4 | 2725 | |
bba1a2c7 | 2726 | @itemize @bullet |
a0e07ba4 | 2727 | @item |
bba1a2c7 | 2728 | @code{method-more-specific?} (generic) |
a0e07ba4 NJ |
2729 | @end itemize |
2730 | ||
bba1a2c7 NJ |
2731 | @item |
2732 | @code{apply-methods} (generic) | |
a0e07ba4 NJ |
2733 | |
2734 | @itemize @bullet | |
2735 | @item | |
bba1a2c7 | 2736 | @code{apply-method} (generic) |
a0e07ba4 | 2737 | |
a0e07ba4 | 2738 | @item |
bba1a2c7 | 2739 | @code{no-next-method} (generic) |
a0e07ba4 NJ |
2740 | @end itemize |
2741 | ||
a0e07ba4 | 2742 | @item |
bba1a2c7 | 2743 | @code{no-applicable-method} |
a0e07ba4 | 2744 | @end itemize |
0b452f2c | 2745 | |
bba1a2c7 NJ |
2746 | We do not yet have full documentation for these. Please refer to the |
2747 | code (@file{oop/goops.scm}) for details. | |
2748 | ||
0b452f2c | 2749 | |
0b452f2c NJ |
2750 | @node Redefining a Class |
2751 | @section Redefining a Class | |
2752 | ||
2753 | Suppose that a class @code{<my-class>} is defined using @code{define-class} | |
2754 | (@pxref{Class Definition,, define-class}), with slots that have | |
2755 | accessor functions, and that an application has created several instances | |
2756 | of @code{<my-class>} using @code{make} (@pxref{Instance Creation,, | |
2757 | make}). What then happens if @code{<my-class>} is redefined by calling | |
2758 | @code{define-class} again? | |
2759 | ||
2760 | @menu | |
2761 | * Default Class Redefinition Behaviour:: | |
2762 | * Customizing Class Redefinition:: | |
2763 | @end menu | |
2764 | ||
2765 | @node Default Class Redefinition Behaviour | |
2766 | @subsection Default Class Redefinition Behaviour | |
2767 | ||
2768 | GOOPS' default answer to this question is as follows. | |
2769 | ||
2770 | @itemize @bullet | |
2771 | @item | |
2772 | All existing direct instances of @code{<my-class>} are converted to be | |
2773 | instances of the new class. This is achieved by preserving the values | |
2774 | of slots that exist in both the old and new definitions, and | |
2775 | initializing the values of new slots in the usual way (@pxref{Instance | |
2776 | Creation,, make}). | |
2777 | ||
2778 | @item | |
2779 | All existing subclasses of @code{<my-class>} are redefined, as though | |
2780 | the @code{define-class} expressions that defined them were re-evaluated | |
2781 | following the redefinition of @code{<my-class>}, and the class | |
2782 | redefinition process described here is applied recursively to the | |
2783 | redefined subclasses. | |
2784 | ||
2785 | @item | |
2786 | Once all of its instances and subclasses have been updated, the class | |
2787 | metaobject previously bound to the variable @code{<my-class>} is no | |
2788 | longer needed and so can be allowed to be garbage collected. | |
2789 | @end itemize | |
2790 | ||
2791 | To keep things tidy, GOOPS also needs to do a little housekeeping on | |
2792 | methods that are associated with the redefined class. | |
2793 | ||
2794 | @itemize @bullet | |
2795 | @item | |
2796 | Slot accessor methods for slots in the old definition should be removed | |
2797 | from their generic functions. They will be replaced by accessor methods | |
2798 | for the slots of the new class definition. | |
2799 | ||
2800 | @item | |
2801 | Any generic function method that uses the old @code{<my-class>} metaobject | |
2802 | as one of its formal parameter specializers must be updated to refer to | |
2803 | the new @code{<my-class>} metaobject. (Whenever a new generic function | |
2804 | method is defined, @code{define-method} adds the method to a list stored | |
2805 | in the class metaobject for each class used as a formal parameter | |
2806 | specializer, so it is easy to identify all the methods that must be | |
2807 | updated when a class is redefined.) | |
2808 | @end itemize | |
2809 | ||
2810 | If this class redefinition strategy strikes you as rather counter-intuitive, | |
2811 | bear in mind that it is derived from similar behaviour in other object | |
2812 | systems such as CLOS, and that experience in those systems has shown it to be | |
2813 | very useful in practice. | |
2814 | ||
2815 | Also bear in mind that, like most of GOOPS' default behaviour, it can | |
2816 | be customized@dots{} | |
2817 | ||
2818 | @node Customizing Class Redefinition | |
2819 | @subsection Customizing Class Redefinition | |
2820 | ||
ed478161 NJ |
2821 | When @code{define-class} notices that a class is being redefined, it |
2822 | constructs the new class metaobject as usual, then invokes the | |
0b452f2c NJ |
2823 | @code{class-redefinition} generic function with the old and new classes |
2824 | as arguments. Therefore, if the old or new classes have metaclasses | |
2825 | other than the default @code{<class>}, class redefinition behaviour can | |
2826 | be customized by defining a @code{class-redefinition} method that is | |
2827 | specialized for the relevant metaclasses. | |
2828 | ||
2829 | @deffn generic class-redefinition | |
2830 | Handle the class redefinition from @var{old-class} to @var{new-class}, | |
2831 | and return the new class metaobject that should be bound to the | |
2832 | variable specified by @code{define-class}'s first argument. | |
2833 | @end deffn | |
2834 | ||
2835 | @deffn method class-redefinition (old-class <class>) (new-class <class>) | |
2836 | Implements GOOPS' default class redefinition behaviour, as described in | |
2837 | @ref{Default Class Redefinition Behaviour}. Returns the metaobject | |
2838 | for the new class definition. | |
2839 | @end deffn | |
2840 | ||
ed478161 NJ |
2841 | The default @code{class-redefinition} method, for classes with the |
2842 | default metaclass @code{<class>}, calls the following generic functions, | |
2843 | which could of course be individually customized. | |
2844 | ||
2845 | @deffn generic remove-class-accessors! old | |
2846 | The default @code{remove-class-accessors!} method removes the accessor | |
2847 | methods of the old class from all classes which they specialize. | |
2848 | @end deffn | |
2849 | ||
2850 | @deffn generic update-direct-method! method old new | |
2851 | The default @code{update-direct-method!} method substitutes the new | |
2852 | class for the old in all methods specialized to the old class. | |
2853 | @end deffn | |
2854 | ||
2855 | @deffn generic update-direct-subclass! subclass old new | |
2856 | The default @code{update-direct-subclass!} method invokes | |
2857 | @code{class-redefinition} recursively to handle the redefinition of | |
2858 | subclasses. | |
2859 | @end deffn | |
2860 | ||
0b452f2c NJ |
2861 | An alternative class redefinition strategy could be to leave all |
2862 | existing instances as instances of the old class, but accepting that the | |
2863 | old class is now ``nameless'', since its name has been taken over by the | |
2864 | new definition. In this strategy, any existing subclasses could also | |
2865 | be left as they are, on the understanding that they inherit from a nameless | |
2866 | superclass. | |
2867 | ||
2868 | This strategy is easily implemented in GOOPS, by defining a new metaclass, | |
2869 | that will be used as the metaclass for all classes to which the strategy | |
2870 | should apply, and then defining a @code{class-redefinition} method that | |
2871 | is specialized for this metaclass: | |
2872 | ||
2873 | @example | |
2874 | (define-class <can-be-nameless> (<class>)) | |
2875 | ||
2876 | (define-method (class-redefinition (old <can-be-nameless>) | |
2877 | (new <class>)) | |
2878 | new) | |
2879 | @end example | |
2880 | ||
2881 | When customization can be as easy as this, aren't you glad that GOOPS | |
2882 | implements the far more difficult strategy as its default! | |
2883 | ||
0b452f2c NJ |
2884 | |
2885 | @node Changing the Class of an Instance | |
2886 | @section Changing the Class of an Instance | |
2887 | ||
ed478161 NJ |
2888 | When a class is redefined, any existing instance of the redefined class |
2889 | will be modified for the new class definition before the next time that | |
2890 | any of the instance's slots is referenced or set. GOOPS modifies each | |
2891 | instance by calling the generic function @code{change-class}. | |
0b452f2c | 2892 | |
ed478161 NJ |
2893 | More generally, you can change the class of an existing instance at any |
2894 | time by invoking the generic function @code{change-class} with two | |
2895 | arguments: the instance and the new class. | |
0b452f2c NJ |
2896 | |
2897 | The default method for @code{change-class} decides how to implement the | |
2898 | change of class by looking at the slot definitions for the instance's | |
2899 | existing class and for the new class. If the new class has slots with | |
2900 | the same name as slots in the existing class, the values for those slots | |
2901 | are preserved. Slots that are present only in the existing class are | |
2902 | discarded. Slots that are present only in the new class are initialized | |
2903 | using the corresponding slot definition's init function (@pxref{Classes,, | |
2904 | slot-init-function}). | |
2905 | ||
ed478161 NJ |
2906 | @deffn generic change-class instance new-class |
2907 | @end deffn | |
2908 | ||
0b452f2c NJ |
2909 | @deffn {method} change-class (obj <object>) (new <class>) |
2910 | Modify instance @var{obj} to make it an instance of class @var{new}. | |
2911 | ||
2912 | The value of each of @var{obj}'s slots is preserved only if a similarly named | |
2913 | slot exists in @var{new}; any other slot values are discarded. | |
2914 | ||
2915 | The slots in @var{new} that do not correspond to any of @var{obj}'s | |
2916 | pre-existing slots are initialized according to @var{new}'s slot definitions' | |
2917 | init functions. | |
2918 | @end deffn | |
2919 | ||
ed478161 NJ |
2920 | The default @code{change-class} method also invokes another generic |
2921 | function, @code{update-instance-for-different-class}, as the last thing | |
2922 | that it does before returning. The applied | |
2923 | @code{update-instance-for-different-class} method can make any further | |
2924 | adjustments to @var{new-instance} that are required to complete or | |
2925 | modify the change of class. The return value from the applied method is | |
2926 | ignored. | |
2927 | ||
2928 | @deffn generic update-instance-for-different-class old-instance new-instance | |
2929 | A generic function that can be customized to put finishing touches to an | |
2930 | instance whose class has just been changed. The default | |
2931 | @code{update-instance-for-different-class} method does nothing. | |
2932 | @end deffn | |
2933 | ||
0b452f2c NJ |
2934 | Customized change of class behaviour can be implemented by defining |
2935 | @code{change-class} methods that are specialized either by the class | |
2936 | of the instances to be modified or by the metaclass of the new class. |