Here is a summary diagram of the syntax, procedures and generic functions that may be involved in class definition.
define-class
(syntax)
class
(syntax)
make-class
(procedure)
ensure-metaclass
(procedure)
make metaclass …
(generic)
allocate-instance
(generic)
initialize
(generic)
compute-cpl
(generic)
compute-std-cpl
(procedure)
compute-slots
(generic)
compute-get-n-set
(generic)
compute-getter-method
(generic)
compute-setter-method
(generic)
class-redefinition
(generic)
remove-class-accessors
(generic)
update-direct-method!
(generic)
update-direct-subclass!
(generic)
Wherever a step above is marked as “generic”, it can be customized,
and the detail shown below it is only “correct” insofar as it
describes what the default method of that generic function does. For
example, if you write an initialize
method, for some metaclass,
that does not call next-method
and does not call
compute-cpl
, then compute-cpl
will not be called when a
class is defined with that metaclass.
A (define-class ...)
form (see Class Definition) expands to
an expression which
class
to create the new class
class-redefinition
(see Redefining a Class).
Return a newly created class that inherits from supers, with direct slots defined by slot-definitions and class-options. For the format of slot-definitions and class-options, see define-class.
class
expands to an expression which
#:init-form
option to an
#:init-thunk
option, to supply a default environment parameter
(the current top-level environment) and to evaluate all the bits that
need to be evaluated
make-class
to create the class with the processed and
evaluated parameters.
Return a newly created class that inherits from supers, with
direct slots defined by slots and class-options. For the
format of slots and class-options, see define-class, except note that for make-class
,
slots is a separate list of slot definitions.
make-class
<object>
to the supers list if supers is empty
or if none of the classes in supers have <object>
in their
class precedence list
#:environment
, #:name
and #:metaclass
options, if they are not specified by options, to the current
top-level environment, the unbound value, and (ensure-metaclass
supers)
respectively
make
, passing the metaclass as the first parameter and all
other parameters as option keywords with values.
Return a metaclass suitable for a class that inherits from the list of classes in supers. The returned metaclass is the union by inheritance of the metaclasses of the classes in supers.
In the simplest case, where all the supers are straightforward
classes with metaclass <class>
, the returned metaclass is just
<class>
.
For a more complex example, suppose that supers contained one
class with metaclass <operator-class>
and one with metaclass
<foreign-object-class>
. Then the returned metaclass would be a
class that inherits from both <operator-class>
and
<foreign-object-class>
.
If supers is the empty list, ensure-metaclass
returns the
default GOOPS metaclass <class>
.
GOOPS keeps a list of the metaclasses created by
ensure-metaclass
, so that each required type of metaclass only
has to be created once.
The env
parameter is ignored.
metaclass is the metaclass of the class being defined, either
taken from the #:metaclass
class option or computed by
ensure-metaclass
. The applied method must create and return the
fully initialized class metaobject for the new class definition.
The (make metaclass initarg …)
invocation is a
particular case of the instance creation protocol covered in the
previous section. It will create an class metaobject with metaclass
metaclass. By default, this metaobject will be initialized by the
initialize
method that is specialized for instances of type
<class>
.
The initialize
method for classes (signature (initialize
<class> initargs)
) calls the following generic functions.
compute-cpl class
(generic)
The applied method should compute and return the class precedence list
for class as a list of class metaobjects. When compute-cpl
is called, the following class metaobject slots have all been
initialized: name
, direct-supers
, direct-slots
,
direct-subclasses
(empty), direct-methods
. The value
returned by compute-cpl
will be stored in the cpl
slot.
compute-slots class
(generic)
The applied method should compute and return the slots (union of direct
and inherited) for class as a list of slot definitions. When
compute-slots
is called, all the class metaobject slots
mentioned for compute-cpl
have been initialized, plus the
following: cpl
, redefined
(#f
), environment
.
The value returned by compute-slots
will be stored in the
slots
slot.
compute-get-n-set class slot-def
(generic)
initialize
calls compute-get-n-set
for each slot computed
by compute-slots
. The applied method should compute and return a
pair of closures that, respectively, get and set the value of the specified
slot. The get closure should have arity 1 and expect a single argument
that is the instance whose slot value is to be retrieved. The set closure
should have arity 2 and expect two arguments, where the first argument is
the instance whose slot value is to be set and the second argument is the
new value for that slot. The closures should be returned in a two element
list: (list get set)
.
The closures returned by compute-get-n-set
are stored as part of
the value of the class metaobject’s getters-n-setters
slot.
Specifically, the value of this slot is a list with the same number of
elements as there are slots in the class, and each element looks either like
(slot-name-symbol init-function . index)
or like
(slot-name-symbol init-function get set)
Where the get and set closures are replaced by index, the slot is
an instance slot and index is the slot’s index in the underlying
structure: GOOPS knows how to get and set the value of such slots and so
does not need specially constructed get and set closures. Otherwise,
get and set are the closures returned by compute-get-n-set
.
The structure of the getters-n-setters
slot value is important when
understanding the next customizable generic functions that initialize
calls…
compute-getter-method class gns
(generic)
initialize
calls compute-getter-method
for each of the
class’s slots (as determined by compute-slots
) that includes a
#:getter
or #:accessor
slot option. gns is the
element of the class metaobject’s getters-n-setters
slot
that specifies how the slot in question is referenced and set, as
described above under compute-get-n-set
. The applied method
should create and return a method that is specialized for instances of
type class and uses the get closure to retrieve the slot’s value.
initialize
uses add-method!
to add the returned method to
the generic function named by the slot definition’s #:getter
or
#:accessor
option.
compute-setter-method class gns
(generic)
compute-setter-method
is invoked with the same arguments as
compute-getter-method
, for each of the class’s slots that includes
a #:setter
or #:accessor
slot option. The applied method
should create and return a method that is specialized for instances of
type class and uses the set closure to set the slot’s value.
initialize
then uses add-method!
to add the returned method
to the generic function named by the slot definition’s #:setter
or #:accessor
option.