From a9bf12c2e59d73a9e7508655c28ffe37a0cc8283 Mon Sep 17 00:00:00 2001 From: Neil Jerram Date: Sat, 25 Sep 2010 15:42:08 +0100 Subject: [PATCH] Start separating doc of the metaobject protocol from that of basic GOOPS usage * doc/ref/goops.texi (Introductory Remarks): Node deleted, with material moved to... (The Metaobject Protocol): ...here. (MOP Specification): Moved to become a subnode of `The Metaobject Protocol'. --- doc/ref/goops.texi | 678 ++++++++++++++++++++++----------------------- 1 file changed, 331 insertions(+), 347 deletions(-) diff --git a/doc/ref/goops.texi b/doc/ref/goops.texi index b53b67a76..34658758e 100644 --- a/doc/ref/goops.texi +++ b/doc/ref/goops.texi @@ -32,7 +32,6 @@ overriding or redefining those methods. * Copyright Notice:: * Quick Start:: * Tutorial:: -* Introductory Remarks:: * Defining New Classes:: * Creating Instances:: * Accessing Slots:: @@ -43,7 +42,7 @@ overriding or redefining those methods. * Changing the Class of an Instance:: * Introspection:: * Miscellaneous Functions:: -* MOP Specification:: +* The Metaobject Protocol:: @end menu @node Copyright Notice @@ -192,339 +191,6 @@ objects, to add two of them together: @section Tutorial @include goops-tutorial.texi -@node Introductory Remarks -@section Introductory Remarks - -GOOPS is an object-oriented programming system based on a ``metaobject -protocol'' derived from the ones used in CLOS (the Common Lisp Object -System), tiny-clos (a small Scheme implementation of a subset of CLOS -functionality) and STKlos. - -GOOPS can be used by application authors at a basic level without any -need to understand what the metaobject protocol (aka ``MOP'') is and how -it works. On the other hand, the MOP underlies even the customizations -that application authors are likely to make use of very quickly --- such -as defining an @code{initialize} method to customize the initialization -of instances of an application-defined class --- and an understanding of -the MOP makes it much easier to explain such customizations in a precise -way. And in the long run, understanding the MOP is the key both to -understanding GOOPS at a deeper level and to taking full advantage of -GOOPS' power, by customizing the behaviour of GOOPS itself. - -Each of the following sections of the reference manual is arranged -such that the most basic usage is introduced first, and then subsequent -subsubsections discuss the related internal functions and metaobject -protocols, finishing with a description of how to customize that area of -functionality. - -These introductory remarks continue with a few words about metaobjects -and the MOP. Readers who do not want to be bothered yet with the MOP -and customization could safely skip this subsubsection on a first reading, -and should correspondingly skip subsequent subsubsections that are -concerned with internals and customization. - -In general, this reference manual assumes familiarity with standard -object oriented concepts and terminology. However, some of the terms -used in GOOPS are less well known, so the Terminology subsubsection -provides definitions for these terms. - -@menu -* Metaobjects and the Metaobject Protocol:: -* Terminology:: -@end menu - -@node Metaobjects and the Metaobject Protocol -@subsection 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 -@code{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 -@code{define-class} itself does not perform this calculation. Instead, -there is a method of the @code{initialize} generic function that is -specialized for instances of type @code{}, and it is this method -that performs the slot calculation. - -@code{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. - -@itemize @bullet -@item -@code{define-class} uses @code{make} to make a new instance of the -@code{}, passing as initialization arguments the superclasses, -slot definitions and class options that were specified in the -@code{define-class} form. - -@item -@code{make} allocates memory for the new instance, and then invokes the -@code{initialize} generic function to initialize the new instance's -slots. - -@item -The @code{initialize} generic function applies the method that is -specialized for instances of type @code{}, and this method -performs the slot calculation. -@end itemize - -In other words, rather than being hardcoded in @code{define-class}, the -behaviour of class definition is encapsulated by generic function -methods that are specialized for the class @code{}. - -It is possible to create a new class that inherits from @code{}, -which is called a ``metaclass'', and to write a new @code{initialize} -method that is specialized for instances of the new metaclass. Then, if -the @code{define-class} form includes a @code{#:metaclass} class option -whose value is the new metaclass, the class that is defined by the -@code{define-class} form will be an instance of the new metaclass rather -than of the default @code{}, and will be defined in accordance -with the new @code{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 @code{}, 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 @code{initialize} method -that is specialized to their application class, to initialize instances -of that class. - -Such is the power of the MOP. Note that @code{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 subsubsection 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 -@code{} or @code{}. (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. - -@node Terminology -@subsection Terminology - -It is assumed that the reader is already familiar with standard object -orientation concepts such as classes, objects/instances, -inheritance/subclassing, generic functions and methods, encapsulation -and polymorphism. - -This section explains some of the less well known concepts and -terminology that GOOPS uses, which are assumed by the following sections -of the reference manual. - -@subsubheading Metaclass - -A @dfn{metaclass} is the class of an object which represents a GOOPS -class. Put more succinctly, a metaclass is a class's class. - -Most GOOPS classes have the metaclass @code{} and, by default, -any new class that is created using @code{define-class} has the -metaclass @code{}. - -But what does this really mean? To find out, let's look in more detail -at what happens when a new class is created using @code{define-class}: - -@example -(define-class () . slots) -@end example - -GOOPS actually expands the @code{define-class} form to something like -this - -@example -(define (class () . slots)) -@end example - -and thence to - -@example -(define - (make #:supers (list ) #:slots slots)) -@end example - -In other words, the value of @code{} is in fact an instance of -the class @code{} with slot values specifying the superclasses -and slot definitions for the class @code{}. (@code{#:supers} -and @code{#:slots} are initialization keywords for the @code{dsupers} -and @code{dslots} slots of the @code{} class.) - -In order to take advantage of the full power of the GOOPS metaobject -protocol (@pxref{MOP Specification}), it is sometimes desirable to -create a new class with a metaclass other than the default -@code{}. This is done by writing: - -@example -(define-class () - slot @dots{} - #:metaclass ) -@end example - -GOOPS expands this to something like: - -@example -(define - (make #:supers (list ) #:slots slots)) -@end example - -In this case, the value of @code{} is an instance of the more -specialized class @code{}. Note that -@code{} itself must previously have been defined as a -subclass of @code{}. For a full discussion of when and how it is -useful to define new metaclasses, see @ref{MOP Specification}. - -Now let's make an instance of @code{}: - -@example -(define my-object (make ...)) -@end example - -All of the following statements are correct expressions of the -relationships between @code{my-object}, @code{}, -@code{} and @code{}. - -@itemize @bullet -@item -@code{my-object} is an instance of the class @code{}. - -@item -@code{} is an instance of the class @code{}. - -@item -@code{} is an instance of the class @code{}. - -@item -The class of @code{my-object} is @code{}. - -@item -The metaclass of @code{my-object} is @code{}. - -@item -The class of @code{} is @code{}. - -@item -The metaclass of @code{} is @code{}. - -@item -The class of @code{} is @code{}. - -@item -The metaclass of @code{} is @code{}. - -@item -@code{} is not a metaclass, since it is does not inherit from -@code{}. - -@item -@code{} is a metaclass, since it inherits from -@code{}. -@end itemize - -@subsubheading Class Precedence List - -The @dfn{class precedence list} of a class is the list of all direct and -indirect superclasses of that class, including the class itself. - -In the absence of multiple inheritance, the class precedence list is -ordered straightforwardly, beginning with the class itself and ending -with @code{}. - -For example, given this inheritance hierarchy: - -@example -(define-class () @dots{}) -(define-class () @dots{}) -(define-class () @dots{}) -@end example - -the class precedence list of would be - -@example -( ) -@end example - -With multiple inheritance, the algorithm is a little more complicated. -A full description is provided by the GOOPS Tutorial: see @ref{Class -precedence list}. - -``Class precedence list'' is often abbreviated, in documentation and -Scheme variable names, to @dfn{cpl}. - -@subsubheading Accessor - -An @dfn{accessor} is a generic function with both reference and setter -methods. - -@example -(define-accessor perimeter) -@end example - -Reference methods for an accessor are defined in the same way as generic -function methods. - -@example -(define-method (perimeter (s )) - (* 4 (side-length s))) -@end example - -Setter methods for an accessor are defined by specifying ``(setter -)'' as the first parameter of the @code{define-method} -call. - -@example -(define-method ((setter perimeter) (s ) (n )) - (set! (side-length s) (/ n 4))) -@end example - -Once an appropriate setter method has been defined in this way, it can -be invoked using the generalized @code{set!} syntax, as in: - -@example -(set! (perimeter s1) 18.3) -@end example - @node Defining New Classes @section Defining New Classes @@ -2487,11 +2153,337 @@ methods - instances of the class @code{}. as the Guile primitive @code{write} and @code{display} functions. @end deffn -@node MOP Specification -@section MOP Specification +@node The Metaobject Protocol +@section The Metaobject Protocol -For an introduction to metaobjects and the metaobject protocol, -see @ref{Metaobjects and the Metaobject Protocol}. +GOOPS is based on a ``metaobject protocol'' derived from the ones used +in CLOS (the Common Lisp Object System), tiny-clos (a small Scheme +implementation of a subset of CLOS functionality) and STKlos. + +GOOPS can be used by application authors at a basic level without any +need to understand what the metaobject protocol (aka ``MOP'') is and how +it works. On the other hand, the MOP underlies even the customizations +that application authors are likely to make use of very quickly --- such +as defining an @code{initialize} method to customize the initialization +of instances of an application-defined class --- and an understanding of +the MOP makes it much easier to explain such customizations in a precise +way. And in the long run, understanding the MOP is the key both to +understanding GOOPS at a deeper level and to taking full advantage of +GOOPS' power, by customizing the behaviour of GOOPS itself. + +These introductory remarks continue with a few words about metaobjects +and the MOP. + +In general, this reference manual assumes familiarity with standard +object oriented concepts and terminology. However, some of the terms +used in GOOPS are less well known, so the Terminology subsubsection +provides definitions for these terms. + +@menu +* Metaobjects and the Metaobject Protocol:: +* Terminology:: +* MOP Specification:: +* Class Definition:: +* Instance Creation:: +* Class Redefinition:: +* Method Definition:: +* Generic Function Invocation:: +@end menu + +@node Metaobjects and the Metaobject Protocol +@subsection 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 +@code{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 +@code{define-class} itself does not perform this calculation. Instead, +there is a method of the @code{initialize} generic function that is +specialized for instances of type @code{}, and it is this method +that performs the slot calculation. + +@code{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. + +@itemize @bullet +@item +@code{define-class} uses @code{make} to make a new instance of the +@code{}, passing as initialization arguments the superclasses, +slot definitions and class options that were specified in the +@code{define-class} form. + +@item +@code{make} allocates memory for the new instance, and then invokes the +@code{initialize} generic function to initialize the new instance's +slots. + +@item +The @code{initialize} generic function applies the method that is +specialized for instances of type @code{}, and this method +performs the slot calculation. +@end itemize + +In other words, rather than being hardcoded in @code{define-class}, the +behaviour of class definition is encapsulated by generic function +methods that are specialized for the class @code{}. + +It is possible to create a new class that inherits from @code{}, +which is called a ``metaclass'', and to write a new @code{initialize} +method that is specialized for instances of the new metaclass. Then, if +the @code{define-class} form includes a @code{#:metaclass} class option +whose value is the new metaclass, the class that is defined by the +@code{define-class} form will be an instance of the new metaclass rather +than of the default @code{}, and will be defined in accordance +with the new @code{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 @code{}, 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 @code{initialize} method +that is specialized to their application class, to initialize instances +of that class. + +Such is the power of the MOP. Note that @code{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 subsubsection 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 +@code{} or @code{}. (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. + +@node Terminology +@subsection Terminology + +It is assumed that the reader is already familiar with standard object +orientation concepts such as classes, objects/instances, +inheritance/subclassing, generic functions and methods, encapsulation +and polymorphism. + +This section explains some of the less well known concepts and +terminology that GOOPS uses, which are assumed by the following sections +of the reference manual. + +@subsubheading Metaclass + +A @dfn{metaclass} is the class of an object which represents a GOOPS +class. Put more succinctly, a metaclass is a class's class. + +Most GOOPS classes have the metaclass @code{} and, by default, +any new class that is created using @code{define-class} has the +metaclass @code{}. + +But what does this really mean? To find out, let's look in more detail +at what happens when a new class is created using @code{define-class}: + +@example +(define-class () . slots) +@end example + +GOOPS actually expands the @code{define-class} form to something like +this + +@example +(define (class () . slots)) +@end example + +and thence to + +@example +(define + (make #:supers (list ) #:slots slots)) +@end example + +In other words, the value of @code{} is in fact an instance of +the class @code{} with slot values specifying the superclasses +and slot definitions for the class @code{}. (@code{#:supers} +and @code{#:slots} are initialization keywords for the @code{dsupers} +and @code{dslots} slots of the @code{} class.) + +In order to take advantage of the full power of the GOOPS metaobject +protocol (@pxref{MOP Specification}), it is sometimes desirable to +create a new class with a metaclass other than the default +@code{}. This is done by writing: + +@example +(define-class () + slot @dots{} + #:metaclass ) +@end example + +GOOPS expands this to something like: + +@example +(define + (make #:supers (list ) #:slots slots)) +@end example + +In this case, the value of @code{} is an instance of the more +specialized class @code{}. Note that +@code{} itself must previously have been defined as a +subclass of @code{}. For a full discussion of when and how it is +useful to define new metaclasses, see @ref{MOP Specification}. + +Now let's make an instance of @code{}: + +@example +(define my-object (make ...)) +@end example + +All of the following statements are correct expressions of the +relationships between @code{my-object}, @code{}, +@code{} and @code{}. + +@itemize @bullet +@item +@code{my-object} is an instance of the class @code{}. + +@item +@code{} is an instance of the class @code{}. + +@item +@code{} is an instance of the class @code{}. + +@item +The class of @code{my-object} is @code{}. + +@item +The metaclass of @code{my-object} is @code{}. + +@item +The class of @code{} is @code{}. + +@item +The metaclass of @code{} is @code{}. + +@item +The class of @code{} is @code{}. + +@item +The metaclass of @code{} is @code{}. + +@item +@code{} is not a metaclass, since it is does not inherit from +@code{}. + +@item +@code{} is a metaclass, since it inherits from +@code{}. +@end itemize + +@subsubheading Class Precedence List + +The @dfn{class precedence list} of a class is the list of all direct and +indirect superclasses of that class, including the class itself. + +In the absence of multiple inheritance, the class precedence list is +ordered straightforwardly, beginning with the class itself and ending +with @code{}. + +For example, given this inheritance hierarchy: + +@example +(define-class () @dots{}) +(define-class () @dots{}) +(define-class () @dots{}) +@end example + +the class precedence list of would be + +@example +( ) +@end example + +With multiple inheritance, the algorithm is a little more complicated. +A full description is provided by the GOOPS Tutorial: see @ref{Class +precedence list}. + +``Class precedence list'' is often abbreviated, in documentation and +Scheme variable names, to @dfn{cpl}. + +@subsubheading Accessor + +An @dfn{accessor} is a generic function with both reference and setter +methods. + +@example +(define-accessor perimeter) +@end example + +Reference methods for an accessor are defined in the same way as generic +function methods. + +@example +(define-method (perimeter (s )) + (* 4 (side-length s))) +@end example + +Setter methods for an accessor are defined by specifying ``(setter +)'' as the first parameter of the @code{define-method} +call. + +@example +(define-method ((setter perimeter) (s ) (n )) + (set! (side-length s) (/ n 4))) +@end example + +Once an appropriate setter method has been defined in this way, it can +be invoked using the generalized @code{set!} syntax, as in: + +@example +(set! (perimeter s1) 18.3) +@end example + +@node MOP Specification +@subsection MOP Specification The aim of the MOP specification in this chapter is to specify all the customizable generic function invocations that can be made by the standard @@ -2534,14 +2526,6 @@ effects what the caller expects to get as the applied method's return value. @end itemize -@menu -* Class Definition:: -* Instance Creation:: -* Class Redefinition:: -* Method Definition:: -* Generic Function Invocation:: -@end menu - @node Class Definition @subsection Class Definition