| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Suppose that a class <my-class> is defined using define-class
(see section define-class), with slots that have
accessor functions, and that an application has created several instances
of <my-class> using make (see section make). What then happens if <my-class> is redefined by calling
define-class again?
2.8.1 Default Class Redefinition Behaviour 2.8.2 Customizing Class Redefinition
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
GOOPS' default answer to this question is as follows.
<my-class> are converted to be
instances of the new class. This is achieved by preserving the values
of slots that exist in both the old and new definitions, and initializing the
values of new slots in the usual way (see section make).
<my-class> are redefined, as though
the define-class expressions that defined them were re-evaluated
following the redefinition of <my-class>, and the class
redefinition process described here is applied recursively to the
redefined subclasses.
<my-class> is no
longer needed and so can be allowed to be garbage collected.
To keep things tidy, GOOPS also needs to do a little housekeeping on methods that are associated with the redefined class.
<my-class> metaobject
as one of its formal parameter specializers must be updated to refer to
the new <my-class> metaobject. (Whenever a new generic function
method is defined, define-method adds the method to a list stored
in the class metaobject for each class used as a formal parameter
specializer, so it is easy to identify all the methods that must be
updated when a class is redefined.)
If this class redefinition strategy strikes you as rather counter-intuitive, bear in mind that it is derived from similar behaviour in other object systems such as CLOS, and that experience in those systems has shown it to be very useful in practice.
Also bear in mind that, like most of GOOPS' default behaviour, it can be customized...
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
When define-class notices that a class is being redefined,
it constructs the new class metaobject as usual, and then invokes the
class-redefinition generic function with the old and new classes
as arguments. Therefore, if the old or new classes have metaclasses
other than the default <class>, class redefinition behaviour can
be customized by defining a class-redefinition method that is
specialized for the relevant metaclasses.
define-class's first argument.
An alternative class redefinition strategy could be to leave all existing instances as instances of the old class, but accepting that the old class is now "nameless", since its name has been taken over by the new definition. In this strategy, any existing subclasses could also be left as they are, on the understanding that they inherit from a nameless superclass.
This strategy is easily implemented in GOOPS, by defining a new metaclass,
that will be used as the metaclass for all classes to which the strategy
should apply, and then defining a class-redefinition method that
is specialized for this metaclass:
(define-class <can-be-nameless> (<class>)) (define-method (class-redefinition (old <can-be-nameless>) (new <class>)) new) |
When customization can be as easy as this, aren't you glad that GOOPS implements the far more difficult strategy as its default!
Finally, note that, if class-redefinition itself is not customized,
the default class-redefinition method invokes three further
generic functions that could be individually customized:
and the default methods for these generic functions invoke further generic functions, and so on... The detailed protocol for all of these is described in 3. MOP Specification.
| [ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |