mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 03:40:34 +02:00
Updated GOOPS sections of reference
* doc/ref/goops.texi: Insert reference to the "definition" of next-method the first time next-method is mentioned. Place the definition of next-method in index. Don't use capital methods in generic function names (corrected only in one node). In section about next-method, say that you can provide custom arguments (which we can now due to the optimizing compiler). New node "Inheritance and accessors" explaining how new accessor methods are created for subclasses.
This commit is contained in:
parent
20405089de
commit
c78abcb765
1 changed files with 57 additions and 30 deletions
|
@ -192,10 +192,10 @@ understood by whatever methods get applied when the @code{initialize}
|
||||||
generic function is applied to the newly allocated instance.
|
generic function is applied to the newly allocated instance.
|
||||||
|
|
||||||
In practice, specialized @code{initialize} methods would normally call
|
In practice, specialized @code{initialize} methods would normally call
|
||||||
@code{(next-method)}, and so eventually the standard GOOPS
|
@code{(next-method)} (@pxref{Next-method}), and so eventually the
|
||||||
@code{initialize} methods are applied. These methods expect
|
standard GOOPS @code{initialize} methods are applied. These methods
|
||||||
@var{initargs} to be a list with an even number of elements, where
|
expect @var{initargs} to be a list with an even number of elements,
|
||||||
even-numbered elements (counting from zero) are keywords and
|
where even-numbered elements (counting from zero) are keywords and
|
||||||
odd-numbered elements are the corresponding values.
|
odd-numbered elements are the corresponding values.
|
||||||
|
|
||||||
GOOPS processes initialization argument keywords automatically for slots
|
GOOPS processes initialization argument keywords automatically for slots
|
||||||
|
@ -857,6 +857,7 @@ to that descendant's ancestors too.
|
||||||
@node Next-method
|
@node Next-method
|
||||||
@subsection Next-method
|
@subsection Next-method
|
||||||
|
|
||||||
|
@fnindex next-method
|
||||||
When you call a generic function, with a particular set of arguments,
|
When you call a generic function, with a particular set of arguments,
|
||||||
GOOPS builds a list of all the methods that are applicable to those
|
GOOPS builds a list of all the methods that are applicable to those
|
||||||
arguments and orders them by how closely the method definitions match
|
arguments and orders them by how closely the method definitions match
|
||||||
|
@ -865,45 +866,40 @@ list. If the selected method's code wants to call on to the next method
|
||||||
in this list, it can do so by using @code{next-method}.
|
in this list, it can do so by using @code{next-method}.
|
||||||
|
|
||||||
@lisp
|
@lisp
|
||||||
(define-method (Test (a <integer>)) (cons 'integer (next-method)))
|
(define-method (test (a <integer>)) (cons 'integer (next-method)))
|
||||||
(define-method (Test (a <number>)) (cons 'number (next-method)))
|
(define-method (test (a <number>)) (cons 'number (next-method)))
|
||||||
(define-method (Test a) (list 'top))
|
(define-method (test a) (list 'top))
|
||||||
@end lisp
|
@end lisp
|
||||||
|
|
||||||
With these definitions,
|
With these definitions,
|
||||||
|
|
||||||
@lisp
|
@lisp
|
||||||
(Test 1) @result{} (integer number top)
|
(test 1) @result{} (integer number top)
|
||||||
(Test 1.0) @result{} (number top)
|
(test 1.0) @result{} (number top)
|
||||||
(Test #t) @result{} (top)
|
(test #t) @result{} (top)
|
||||||
@end lisp
|
@end lisp
|
||||||
|
|
||||||
@code{next-method} is always called as just @code{(next-method)}. The
|
@code{next-method} can be called as just @code{(next-method)}. The
|
||||||
arguments for the next method call are always implicit, and always the
|
arguments for the next method call are then implicit, and the same as
|
||||||
same as for the original method call.
|
for the original method call.
|
||||||
|
|
||||||
If you want to call on to a method with the same name but with a
|
If you want to call on to a method with the same name but with a
|
||||||
different set of arguments (as you might with overloaded methods in C++,
|
different set of arguments (as you might with overloaded methods in C++,
|
||||||
for example), you do not use @code{next-method}, but instead simply
|
for example), you can pass custom arguments to @code{next-method}:
|
||||||
write the new call as usual:
|
|
||||||
|
|
||||||
@lisp
|
@lisp
|
||||||
(define-method (Test (a <number>) min max)
|
(define-method (test (a <number>) min max)
|
||||||
(if (and (>= a min) (<= a max))
|
(if (and (>= a min) (<= a max))
|
||||||
(display "Number is in range\n"))
|
(display "Number is in range\n"))
|
||||||
(Test a))
|
(next-method a))
|
||||||
|
|
||||||
(Test 2 1 10)
|
(test 2 1 10)
|
||||||
@print{}
|
@print{}
|
||||||
Number is in range
|
Number is in range
|
||||||
@result{}
|
@result{}
|
||||||
(integer number top)
|
(integer number top)
|
||||||
@end lisp
|
@end lisp
|
||||||
|
|
||||||
(You should be careful in this case that the @code{Test} calls do not
|
|
||||||
lead to an infinite recursion, but this consideration is just the same
|
|
||||||
as in Scheme code in general.)
|
|
||||||
|
|
||||||
@node method* and define-method*
|
@node method* and define-method*
|
||||||
@subsection method* and define-method*
|
@subsection method* and define-method*
|
||||||
|
|
||||||
|
@ -1042,10 +1038,9 @@ in the same position in less specialized methods. For example if
|
||||||
@var{<B>},
|
@var{<B>},
|
||||||
|
|
||||||
@lisp
|
@lisp
|
||||||
> (define-method* (foo (obj <A>) #:optional (c 1)) c)
|
(define-method* (foo (obj <A>) #:optional (c 1)) c)
|
||||||
> (define-method* (foo (obj <B>) #:optional c)) (next-method))
|
(define-method* (foo (obj <B>) #:optional c)) (next-method))
|
||||||
> (foo b)
|
(foo b) @result{} #f
|
||||||
$1 = #f
|
|
||||||
@end lisp
|
@end lisp
|
||||||
|
|
||||||
The reason for this is that @var{c} will obtain the value @code{#f}
|
The reason for this is that @var{c} will obtain the value @code{#f}
|
||||||
|
@ -1058,10 +1053,9 @@ A keyword argument will not shadow a default value for the same keyword
|
||||||
argument in less specialized methods. Example:
|
argument in less specialized methods. Example:
|
||||||
|
|
||||||
@lisp
|
@lisp
|
||||||
> (define-method* (foo (obj <A>) #:key (c 1)) c)
|
(define-method* (foo (obj <A>) #:key (c 1)) c)
|
||||||
> (define-method* (foo (obj <B>) #:key c)) (next-method))
|
(define-method* (foo (obj <B>) #:key c)) (next-method))
|
||||||
> (foo b)
|
(foo b) @result{} 1
|
||||||
$1 = 1
|
|
||||||
@end lisp
|
@end lisp
|
||||||
|
|
||||||
The reason for this is that the first (less specialized, called last)
|
The reason for this is that the first (less specialized, called last)
|
||||||
|
@ -1362,6 +1356,7 @@ The ordering of the returned slots is not significant.
|
||||||
@menu
|
@menu
|
||||||
* Class Precedence List::
|
* Class Precedence List::
|
||||||
* Sorting Methods::
|
* Sorting Methods::
|
||||||
|
* Inheritance and accessors::
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
|
@ -1476,6 +1471,38 @@ a class C1 is more specific than another class C2, for an object of
|
||||||
actual class C, if C1 comes before C2 in C's class precedence list.
|
actual class C, if C1 comes before C2 in C's class precedence list.
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
|
@node Inheritance and accessors
|
||||||
|
@subsection Inheritance and accessors
|
||||||
|
|
||||||
|
When a class @var{<A>} defines a getter, setter or accessor for one of
|
||||||
|
its slots @var{x}, an @emph{accessor method} specialized to class
|
||||||
|
@var{<A>} is created. Accessor methods are special in that they always
|
||||||
|
refer to a concrete class. When you subclass @var{<A>}, a new accessor
|
||||||
|
method for @var{x} is created automatically, specialized to the
|
||||||
|
subclass:
|
||||||
|
|
||||||
|
@lisp
|
||||||
|
(define-class <A> () (x #:accessor x))
|
||||||
|
(define-class <B> (<A>))
|
||||||
|
(generic-function-methods x)
|
||||||
|
@result{}
|
||||||
|
(#<<accessor-method> (<B>) 7faa66b5b1c0>
|
||||||
|
#<<accessor-method> (<A>) 7faa66b5b240>)
|
||||||
|
@end lisp
|
||||||
|
|
||||||
|
Note, in particular, that the @var{x} accessor method specialized to
|
||||||
|
@var{<A>} is @emph{not} applicable to objects of class @var{B}:
|
||||||
|
|
||||||
|
@lisp
|
||||||
|
(define o (make <B>))
|
||||||
|
(compute-applicable-methods x (list o))
|
||||||
|
@result{}
|
||||||
|
(#<<accessor-method> (<B>) 7faa66b5b1c0>)
|
||||||
|
@end lisp
|
||||||
|
|
||||||
|
As a consequence, an accessor doesn't have a next-method. The fact that
|
||||||
|
accessor methods always apply to concrete classes allows for extensive
|
||||||
|
optimization.
|
||||||
|
|
||||||
@node Introspection
|
@node Introspection
|
||||||
@section Introspection
|
@section Introspection
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue