(goops.info.gz) Customizing Class Definition
Info Catalog
(goops.info.gz) Class Definition Internals
(goops.info.gz) Defining New Classes
(goops.info.gz) STKlos Compatibility
Customizing Class Definition
----------------------------
During the initialization of a new class, GOOPS calls a number of
generic functions with the newly allocated class instance as the first
argument. Specifically, GOOPS calls the generic function
* (initialize CLASS ...)
where CLASS is the newly allocated class instance, and the default
`initialize' method for arguments of type `<class>' calls the generic
functions
* (compute-cpl CLASS)
* (compute-slots CLASS)
* (compute-get-n-set CLASS SLOT-DEF), for each of the slot
definitions returned by `compute-slots'
* (compute-getter-method CLASS SLOT-DEF), for each of the slot
definitions returned by `compute-slots' that includes a `#:getter'
or `#:accessor' slot option
* (compute-setter-method CLASS SLOT-DEF), for each of the slot
definitions returned by `compute-slots' that includes a `#:setter'
or `#:accessor' slot option.
If the metaclass of the new class is something more specialized than the
default `<class>', then the type of CLASS in the calls above is more
specialized than `<class>', and hence it becomes possible to define
generic function methods, specialized for the new class's metaclass,
that can modify or override the default behaviour of `initialize',
`compute-cpl' or `compute-get-n-set'.
`compute-cpl' computes the class precedence list ("CPL") for the new
class ( Class precedence list), and returns it as a list of
class objects. The CPL is important because it defines a superclass
ordering that is used, when a generic function is invoked upon an
instance of the class, to decide which of the available generic function
methods is the most specific. Hence `compute-cpl' could be customized
in order to modify the CPL ordering algorithm for all classes with a
special metaclass.
The default CPL algorithm is encapsulated by the `compute-std-cpl'
procedure, which is in turn called by the default `compute-cpl' method.
- procedure: compute-std-cpl class
Compute and return the class precedence list for CLASS according
to the algorithm described in Class precedence list.
`compute-slots' computes and returns a list of all slot definitions for
the new class. By default, this list includes the direct slot
definitions from the `define-class' form, plus the slot definitions
that are inherited from the new class's superclasses. The default
`compute-slots' method uses the CPL computed by `compute-cpl' to
calculate this union of slot definitions, with the rule that slots
inherited from superclasses are shadowed by direct slots with the same
name. One possible reason for customizing `compute-slots' would be to
implement an alternative resolution strategy for slot name conflicts.
`compute-get-n-set' computes the low-level closures that will be used
to get and set the value of a particular slot, and returns them in a
list with two elements.
The closures returned depend on how storage for that slot is allocated.
The standard `compute-get-n-set' method, specialized for classes of
type `<class>', handles the standard GOOPS values for the
`#:allocation' slot option ( allocation Slot Options.). By
defining a new `compute-get-n-set' method for a more specialized
metaclass, it is possible to support new types of slot allocation.
Suppose you wanted to create a large number of instances of some class
with a slot that should be shared between some but not all instances of
that class - say every 10 instances should share the same slot storage.
The following example shows how to implement and use a new type of slot
allocation to do this.
(define-class <batched-allocation-metaclass> (<class>))
(let ((batch-allocation-count 0)
(batch-get-n-set #f))
(define-method (compute-get-n-set (class <batched-allocation-metaclass>) s)
(case (slot-definition-allocation s)
((#:batched)
;; If we've already used the same slot storage for 10 instances,
;; reset variables.
(if (= batch-allocation-count 10)
(begin
(set! batch-allocation-count 0)
(set! batch-get-n-set #f)))
;; If we don't have a current pair of get and set closures,
;; create one. make-closure-variable returns a pair of closures
;; around a single Scheme variable - see goops.scm for details.
(or batch-get-n-set
(set! batch-get-n-set (make-closure-variable)))
;; Increment the batch allocation count.
(set! batch-allocation-count (+ batch-allocation-count 1))
batch-get-n-set)
;; Call next-method to handle standard allocation types.
(else (next-method)))))
(define-class <class-using-batched-slot> ()
...
(c #:allocation #:batched)
...
#:metaclass <batched-allocation-metaclass>)
The usage of `compute-getter-method' and `compute-setter-method' is
described in MOP Specification.
`compute-cpl' and `compute-get-n-set' are called by the standard
`initialize' method for classes whose metaclass is `<class>'. But
`initialize' itself can also be modified, by defining an `initialize'
method specialized to the new class's metaclass. Such a method could
complete override the standard behaviour, by not calling
`(next-method)' at all, but more typically it would perform additional
class initialization steps before and/or after calling `(next-method)'
for the standard behaviour.
Info Catalog
(goops.info.gz) Class Definition Internals
(goops.info.gz) Defining New Classes
(goops.info.gz) STKlos Compatibility
automatically generated byinfo2html