mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-20 11:40:18 +02:00
Work on GOOPS MOP documentation
* doc/ref/goops.texi (The Metaobject Protocol): Simplify intro text. Minor edits and simplifications throughout this section. (Metaobjects and the Metaobject Protocol): Insert "default". (Metaclasses): Renamed from `Terminology', and deleted the material on CPL and accessors, which just duplicated what has already been covered earlier in the chapter. Remove statements that confuse whether "metaclass of" means "class of class of" or "class of (something that is itself a class)". (I think it's actually the latter.) (Class Definition Protocol): Renamed from `Class Definition Internals'.
This commit is contained in:
parent
8fa6525e82
commit
a46f77f95c
1 changed files with 45 additions and 142 deletions
|
@ -1777,21 +1777,19 @@ So let's plunge in. GOOPS is based on a ``metaobject protocol'' (aka
|
||||||
System), tiny-clos (a small Scheme implementation of a subset of CLOS
|
System), tiny-clos (a small Scheme implementation of a subset of CLOS
|
||||||
functionality) and STKlos.
|
functionality) and STKlos.
|
||||||
|
|
||||||
GOOPS can be used by application authors at a basic level without any
|
The MOP underlies many possible GOOPS customizations --- such as
|
||||||
need to understand what the MOP is and how it works. On the other hand,
|
defining an @code{initialize} method to customize the initialization of
|
||||||
the MOP underlies even very simple customizations --- such as defining
|
instances of an application-defined class --- and an understanding of
|
||||||
an @code{initialize} method to customize the initialization of instances
|
the MOP makes it much easier to explain such customizations in a precise
|
||||||
of an application-defined class --- and an understanding of the MOP
|
way. And at a deeper level, understanding the MOP is a key part of
|
||||||
makes it much easier to explain such customizations in a precise way.
|
understanding GOOPS, and of taking full advantage of GOOPS' power, by
|
||||||
And in the long run, understanding the MOP is the key both to
|
customizing the behaviour of GOOPS itself.
|
||||||
understanding GOOPS at a deeper level and to taking full advantage of
|
|
||||||
GOOPS' power, by customizing the behaviour of GOOPS itself.
|
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* Metaobjects and the Metaobject Protocol::
|
* Metaobjects and the Metaobject Protocol::
|
||||||
* Terminology::
|
* Metaclasses::
|
||||||
* MOP Specification::
|
* MOP Specification::
|
||||||
* Class Definition Internals::
|
* Class Definition Protocol::
|
||||||
* Customizing Class Definition::
|
* Customizing Class Definition::
|
||||||
* Customizing Instance Creation::
|
* Customizing Instance Creation::
|
||||||
* Class Redefinition::
|
* Class Redefinition::
|
||||||
|
@ -1828,7 +1826,7 @@ as regards accessibility and protection from garbage collection.
|
||||||
Instances are of course objects in the usual sense, and there is no
|
Instances are of course objects in the usual sense, and there is no
|
||||||
benefit from thinking of them as metaobjects.)
|
benefit from thinking of them as metaobjects.)
|
||||||
|
|
||||||
The ``metaobject protocol'' (aka ``MOP'') is the specification of the
|
The ``metaobject protocol'' (or ``MOP'') is the specification of the
|
||||||
generic functions which determine the behaviour of these metaobjects and
|
generic functions which determine the behaviour of these metaobjects and
|
||||||
the circumstances in which these generic functions are invoked.
|
the circumstances in which these generic functions are invoked.
|
||||||
|
|
||||||
|
@ -1854,7 +1852,7 @@ superclasses, slot definitions and class options that were specified in
|
||||||
the @code{define-class} form.
|
the @code{define-class} form.
|
||||||
|
|
||||||
@item
|
@item
|
||||||
@code{make} allocates memory for the new instance, and then invokes the
|
@code{make} allocates memory for the new instance, and invokes the
|
||||||
@code{initialize} generic function to initialize the new instance's
|
@code{initialize} generic function to initialize the new instance's
|
||||||
slots.
|
slots.
|
||||||
|
|
||||||
|
@ -1865,8 +1863,8 @@ performs the slot calculation.
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
In other words, rather than being hardcoded in @code{define-class}, the
|
In other words, rather than being hardcoded in @code{define-class}, the
|
||||||
behaviour of class definition is encapsulated by generic function
|
default behaviour of class definition is encapsulated by generic
|
||||||
methods that are specialized for the class @code{<class>}.
|
function methods that are specialized for the class @code{<class>}.
|
||||||
|
|
||||||
It is possible to create a new class that inherits from @code{<class>},
|
It is possible to create a new class that inherits from @code{<class>},
|
||||||
which is called a ``metaclass'', and to write a new @code{initialize}
|
which is called a ``metaclass'', and to write a new @code{initialize}
|
||||||
|
@ -1897,19 +1895,8 @@ Each following section covers a particular area of GOOPS functionality,
|
||||||
and describes the generic functions that are relevant for customization
|
and describes the generic functions that are relevant for customization
|
||||||
of that area.
|
of that area.
|
||||||
|
|
||||||
@node Terminology
|
@node Metaclasses
|
||||||
@subsection Terminology
|
@subsection Metaclasses
|
||||||
|
|
||||||
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
|
A @dfn{metaclass} is the class of an object which represents a GOOPS
|
||||||
class. Put more succinctly, a metaclass is a class's class.
|
class. Put more succinctly, a metaclass is a class's class.
|
||||||
|
@ -1925,30 +1912,29 @@ at what happens when a new class is created using @code{define-class}:
|
||||||
(define-class <my-class> (<object>) . slots)
|
(define-class <my-class> (<object>) . slots)
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
GOOPS actually expands the @code{define-class} form to something like
|
@noindent
|
||||||
this
|
Guile expands this to something like:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
(define <my-class> (class (<object>) . slots))
|
(define <my-class> (class (<object>) . slots))
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
and thence to
|
@noindent
|
||||||
|
which in turn expands to:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
(define <my-class>
|
(define <my-class>
|
||||||
(make <class> #:supers (list <object>) #:slots slots))
|
(make <class> #:supers (list <object>) #:slots slots))
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
In other words, the value of @code{<my-class>} is in fact an instance of
|
As this expansion makes clear, the resulting value of @code{<my-class>}
|
||||||
the class @code{<class>} with slot values specifying the superclasses
|
is an instance of the class @code{<class>} with slot values specifying
|
||||||
and slot definitions for the class @code{<my-class>}. (@code{#:supers}
|
the superclasses and slot definitions for the class @code{<my-class>}.
|
||||||
and @code{#:slots} are initialization keywords for the @code{dsupers}
|
(@code{#:supers} and @code{#:slots} are initialization keywords for the
|
||||||
and @code{dslots} slots of the @code{<class>} class.)
|
@code{dsupers} and @code{dslots} slots of the @code{<class>} class.)
|
||||||
|
|
||||||
In order to take advantage of the full power of the GOOPS metaobject
|
Now suppose that you want to define a new class with a metaclass other
|
||||||
protocol (@pxref{MOP Specification}), it is sometimes desirable to
|
than the default @code{<class>}. This is done by writing:
|
||||||
create a new class with a metaclass other than the default
|
|
||||||
@code{<class>}. This is done by writing:
|
|
||||||
|
|
||||||
@example
|
@example
|
||||||
(define-class <my-class2> (<object>)
|
(define-class <my-class2> (<object>)
|
||||||
|
@ -1956,7 +1942,8 @@ create a new class with a metaclass other than the default
|
||||||
#:metaclass <my-metaclass>)
|
#:metaclass <my-metaclass>)
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
GOOPS expands this to something like:
|
@noindent
|
||||||
|
and Guile expands @emph{this} to something like:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
(define <my-class2>
|
(define <my-class2>
|
||||||
|
@ -1992,92 +1979,13 @@ relationships between @code{my-object}, @code{<my-class2>},
|
||||||
@item
|
@item
|
||||||
The class of @code{my-object} is @code{<my-class2>}.
|
The class of @code{my-object} is @code{<my-class2>}.
|
||||||
|
|
||||||
@item
|
|
||||||
The metaclass of @code{my-object} is @code{<my-metaclass>}.
|
|
||||||
|
|
||||||
@item
|
@item
|
||||||
The class of @code{<my-class2>} is @code{<my-metaclass>}.
|
The class of @code{<my-class2>} is @code{<my-metaclass>}.
|
||||||
|
|
||||||
@item
|
|
||||||
The metaclass of @code{<my-class2>} is @code{<class>}.
|
|
||||||
|
|
||||||
@item
|
@item
|
||||||
The class of @code{<my-metaclass>} is @code{<class>}.
|
The class of @code{<my-metaclass>} is @code{<class>}.
|
||||||
|
|
||||||
@item
|
|
||||||
The metaclass of @code{<my-metaclass>} is @code{<class>}.
|
|
||||||
|
|
||||||
@item
|
|
||||||
@code{<my-class2>} is not a metaclass, since it is does not inherit from
|
|
||||||
@code{<class>}.
|
|
||||||
|
|
||||||
@item
|
|
||||||
@code{<my-metaclass>} is a metaclass, since it inherits from
|
|
||||||
@code{<class>}.
|
|
||||||
@end itemize
|
@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{<top>}.
|
|
||||||
|
|
||||||
For example, given this inheritance hierarchy:
|
|
||||||
|
|
||||||
@example
|
|
||||||
(define-class <invertebrate> (<object>) @dots{})
|
|
||||||
(define-class <echinoderm> (<invertebrate>) @dots{})
|
|
||||||
(define-class <starfish> (<echinoderm>) @dots{})
|
|
||||||
@end example
|
|
||||||
|
|
||||||
the class precedence list of <starfish> would be
|
|
||||||
|
|
||||||
@example
|
|
||||||
(<starfish> <echinoderm> <invertebrate> <object> <top>)
|
|
||||||
@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 <square>))
|
|
||||||
(* 4 (side-length s)))
|
|
||||||
@end example
|
|
||||||
|
|
||||||
Setter methods for an accessor are defined by specifying ``(setter
|
|
||||||
<accessor-name>)'' as the first parameter of the @code{define-method}
|
|
||||||
call.
|
|
||||||
|
|
||||||
@example
|
|
||||||
(define-method ((setter perimeter) (s <square>) (n <number>))
|
|
||||||
(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
|
@node MOP Specification
|
||||||
@subsection MOP Specification
|
@subsection MOP Specification
|
||||||
|
@ -2087,22 +1995,17 @@ customizable generic function invocations that can be made by the standard
|
||||||
GOOPS syntax, procedures and methods, and to explain the protocol for
|
GOOPS syntax, procedures and methods, and to explain the protocol for
|
||||||
customizing such invocations.
|
customizing such invocations.
|
||||||
|
|
||||||
A generic function invocation is customizable if the types of the arguments
|
A generic function invocation is customizable if the types of the
|
||||||
to which it is applied are not all determined by the lexical context in
|
arguments to which it is applied are not completely determined by the
|
||||||
which the invocation appears. For example,
|
lexical context in which the invocation appears. For example, the
|
||||||
|
@code{(initialize @var{instance} @var{initargs})} invocation in the
|
||||||
|
default @code{make-instance} method is customizable, because the type of
|
||||||
|
the @code{@var{instance}} argument is determined by the class that was
|
||||||
|
passed to @code{make-instance}.
|
||||||
|
|
||||||
@itemize @bullet
|
(Whereas --- to give a counter-example --- the @code{(make <generic>
|
||||||
@item
|
#:name ',name)} invocation in @code{define-generic} is not customizable,
|
||||||
the @code{(initialize @var{instance} @var{initargs})} invocation in the
|
because all of its arguments have lexically determined types.)
|
||||||
default @code{make-instance} method is customizable, because the type of the
|
|
||||||
@code{@var{instance}} argument is determined by the class that was passed to
|
|
||||||
@code{make-instance}.
|
|
||||||
|
|
||||||
@item
|
|
||||||
the @code{(make <generic> #:name ',name)} invocation in @code{define-generic}
|
|
||||||
is not customizable, because all of its arguments have lexically determined
|
|
||||||
types.
|
|
||||||
@end itemize
|
|
||||||
|
|
||||||
When using this rule to decide whether a given generic function invocation
|
When using this rule to decide whether a given generic function invocation
|
||||||
is customizable, we ignore arguments that are expected to be handled in
|
is customizable, we ignore arguments that are expected to be handled in
|
||||||
|
@ -2123,8 +2026,8 @@ effects
|
||||||
what the caller expects to get as the applied method's return value.
|
what the caller expects to get as the applied method's return value.
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
@node Class Definition Internals
|
@node Class Definition Protocol
|
||||||
@subsection Class Definition Internals
|
@subsection Class Definition Protocol
|
||||||
|
|
||||||
@code{define-class} (syntax)
|
@code{define-class} (syntax)
|
||||||
|
|
||||||
|
@ -2267,7 +2170,7 @@ defines any accessors that are implied by the @var{slot-definition}s
|
||||||
|
|
||||||
@item
|
@item
|
||||||
uses @code{class} to create the new class (@pxref{Class Definition
|
uses @code{class} to create the new class (@pxref{Class Definition
|
||||||
Internals,, class})
|
Protocol,, class})
|
||||||
|
|
||||||
@item
|
@item
|
||||||
checks for a previous class definition for @var{name} and, if found,
|
checks for a previous class definition for @var{name} and, if found,
|
||||||
|
@ -2318,7 +2221,7 @@ class precedence list
|
||||||
defaults the @code{#:environment}, @code{#:name} and @code{#:metaclass}
|
defaults the @code{#:environment}, @code{#:name} and @code{#:metaclass}
|
||||||
options, if they are not specified by @var{options}, to the current
|
options, if they are not specified by @var{options}, to the current
|
||||||
top-level environment, the unbound value, and @code{(ensure-metaclass
|
top-level environment, the unbound value, and @code{(ensure-metaclass
|
||||||
@var{supers})} respectively (@pxref{Class Definition Internals,,
|
@var{supers})} respectively (@pxref{Class Definition Protocol,,
|
||||||
ensure-metaclass})
|
ensure-metaclass})
|
||||||
|
|
||||||
@item
|
@item
|
||||||
|
@ -2357,7 +2260,7 @@ The @code{env} parameter is ignored.
|
||||||
|
|
||||||
@deffn procedure ensure-metaclass-with-supers meta-supers
|
@deffn procedure ensure-metaclass-with-supers meta-supers
|
||||||
@code{ensure-metaclass-with-supers} is an internal procedure used by
|
@code{ensure-metaclass-with-supers} is an internal procedure used by
|
||||||
@code{ensure-metaclass} (@pxref{Class Definition Internals,,
|
@code{ensure-metaclass} (@pxref{Class Definition Protocol,,
|
||||||
ensure-metaclass}). It returns a metaclass that is the union by
|
ensure-metaclass}). It returns a metaclass that is the union by
|
||||||
inheritance of the metaclasses in @var{meta-supers}.
|
inheritance of the metaclasses in @var{meta-supers}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
@ -2886,11 +2789,11 @@ accessor, passing the setter generic function as the value of the
|
||||||
The @code{#:metaclass} class option specifies the metaclass of the class
|
The @code{#:metaclass} class option specifies the metaclass of the class
|
||||||
being defined. @var{metaclass} must be a class that inherits from
|
being defined. @var{metaclass} must be a class that inherits from
|
||||||
@code{<class>}. For the use of metaclasses, see @ref{Metaobjects and
|
@code{<class>}. For the use of metaclasses, see @ref{Metaobjects and
|
||||||
the Metaobject Protocol} and @ref{Terminology}.
|
the Metaobject Protocol} and @ref{Metaclasses}.
|
||||||
|
|
||||||
If the @code{#:metaclass} option is absent, GOOPS reuses or constructs a
|
If the @code{#:metaclass} option is absent, GOOPS reuses or constructs a
|
||||||
metaclass for the new class by calling @code{ensure-metaclass}
|
metaclass for the new class by calling @code{ensure-metaclass}
|
||||||
(@pxref{Class Definition Internals,, ensure-metaclass}).
|
(@pxref{Class Definition Protocol,, ensure-metaclass}).
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {class option} #:name name
|
@deffn {class option} #:name name
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue