DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH
 

(goops.info.gz) Metaobjects and the Metaobject Protocol

Info Catalog (goops.info.gz) Introductory Remarks (goops.info.gz) Terminology
 
 Metaobjects and the Metaobject Protocol
 ---------------------------------------
 
 The conceptual building blocks of GOOPS are classes, slot definitions,
 instances, generic functions and methods.  A class is a grouping of
 inheritance relations and slot definitions.  An instance is an object
 with slots that are allocated following the rules implied by its class's
 superclasses and slot definitions.  A generic function is a collection
 of methods and rules for determining which of those methods to apply
 when the generic function is invoked.  A method is a procedure and a set
 of specializers that specify the type of arguments to which the
 procedure is applicable.
 
 Of these entities, GOOPS represents classes, generic functions and
 methods as "metaobjects".  In other words, the values in a GOOPS
 program that describe classes, generic functions and methods, are
 themselves instances (or "objects") of special GOOPS classes that
 encapsulate the behaviour, respectively, of classes, generic functions,
 and methods.
 
 (The other two entities are slot definitions and instances.  Slot
 definitions are not strictly instances, but every slot definition is
 associated with a GOOPS class that specifies the behaviour of the slot
 as regards accessibility and protection from garbage collection.
 Instances are of course objects in the usual sense, and there is no
 benefit from thinking of them as metaobjects.)
 
 The "metaobject protocol" (aka "MOP") is the specification of the
 generic functions which determine the behaviour of these metaobjects and
 the circumstances in which these generic functions are invoked.
 
 For a concrete example of what this means, consider how GOOPS calculates
 the set of slots for a class that is being defined using
 `define-class'.  The desired set of slots is the union of the new
 class's direct slots and the slots of all its superclasses.  But
 `define-class' itself does not perform this calculation.  Instead,
 there is a method of the `initialize' generic function that is
 specialized for instances of type `<class>', and it is this method that
 performs the slot calculation.
 
 `initialize' is a generic function which GOOPS calls whenever a new
 instance is created, immediately after allocating memory for a new
 instance, in order to initialize the new instance's slots.  The sequence
 of steps is as follows.
 
    * `define-class' uses `make' to make a new instance of the
      `<class>', passing as initialization arguments the superclasses,
      slot definitions and class options that were specified in the
      `define-class' form.
 
    * `make' allocates memory for the new instance, and then invokes the
      `initialize' generic function to initialize the new instance's
      slots.
 
    * The `initialize' generic function applies the method that is
      specialized for instances of type `<class>', and this method
      performs the slot calculation.
 
 In other words, rather than being hardcoded in `define-class', the
 behaviour of class definition is encapsulated by generic function
 methods that are specialized for the class `<class>'.
 
 It is possible to create a new class that inherits from `<class>',
 which is called a "metaclass", and to write a new `initialize' method
 that is specialized for instances of the new metaclass.  Then, if the
 `define-class' form includes a `#:metaclass' class option whose value
 is the new metaclass, the class that is defined by the `define-class'
 form will be an instance of the new metaclass rather than of the
 default `<class>', and will be defined in accordance with the new
 `initialize' method.  Thus the default slot calculation, as well as any
 other aspect of the new class's relationship with its superclasses, can
 be modified or overridden.
 
 In a similar way, the behaviour of generic functions can be modified or
 overridden by creating a new class that inherits from the standard
 generic function class `<generic>', writing appropriate methods that
 are specialized to the new class, and creating new generic functions
 that are instances of the new class.
 
 The same is true for method metaobjects.  And the same basic mechanism
 allows the application class author to write an `initialize' method
 that is specialized to their application class, to initialize instances
 of that class.
 
 Such is the power of the MOP.  Note that `initialize' is just one of a
 large number of generic functions that can be customized to modify the
 behaviour of application objects and classes and of GOOPS itself.  Each
 subsequent section of the reference manual covers a particular area of
 GOOPS functionality, and describes the generic functions that are
 relevant for customization of that area.
 
 We conclude this subsection by emphasizing a point that may seem
 obvious, but contrasts with the corresponding situation in some other
 MOP implementations, such as CLOS.  The point is simply that an
 identifier which represents a GOOPS class or generic function is a
 variable with a first-class value, the value being an instance of class
 `<class>' or `<generic>'.  (In CLOS, on the other hand, a class
 identifier is a symbol that indexes the corresponding class metaobject
 in a separate namespace for classes.)  This is, of course, simply an
 extension of the tendency in Scheme to avoid the unnecessary use of, on
 the one hand, syntactic forms that require unevaluated arguments and,
 on the other, separate identifier namespaces (e.g. for class names),
 but it is worth noting that GOOPS conforms fully to this Schemely
 principle.
 
Info Catalog (goops.info.gz) Introductory Remarks (goops.info.gz) Terminology
automatically generated byinfo2html