diff options
Diffstat (limited to 'doc/next.n')
-rw-r--r-- | doc/next.n | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/doc/next.n b/doc/next.n new file mode 100644 index 0000000..d3f7937 --- /dev/null +++ b/doc/next.n @@ -0,0 +1,203 @@ +'\" +'\" Copyright (c) 2007 Donal K. Fellows +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +.so man.macros +.TH next n 0.1 TclOO "TclOO Commands" +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +next \- invoke superclass method implementations +.SH SYNOPSIS +.nf +package require TclOO + +\fBnext\fR ?\fIarg ...\fR? +\fBnextto\fI class\fR ?\fIarg ...\fR? +.fi +.BE + +.SH DESCRIPTION +.PP +The \fBnext\fR command is used to call implementations of a method by a class, +superclass or mixin that are overridden by the current method. It can only be +used from within a method. It is also used within filters to indicate the +point where a filter calls the actual implementation (the filter may decide to +not go along the chain, and may process the results of going along the chain +of methods as it chooses). The result of the \fBnext\fR command is the result +of the next method in the method chain; if there are no further methods in the +method chain, the result of \fBnext\fR will be an error. The arguments, +\fIarg\fR, to \fBnext\fR are the arguments to pass to the next method in the +chain. +.PP +The \fBnextto\fR command is the same as the \fBnext\fR command, except that it +takes an additional \fIclass\fR argument that identifies a class whose +implementation of the current method chain (see \fBinfo object\fR \fBcall\fR) should +be used; the method implementation selected will be the one provided by the +given class, and it must refer to an existing non-filter invocation that lies +further along the chain than the current implementation. +.SH "THE METHOD CHAIN" +.PP +When a method of an object is invoked, things happen in several stages: +.IP [1] +The structure of the object, its class, superclasses, filters, and mixins, are +examined to build a \fImethod chain\fR, which contains a list of method +implementations to invoke. +.IP [2] +The first method implementation on the chain is invoked. +.IP [3] +If that method implementation invokes the \fBnext\fR command, the next method +implementation is invoked (with its arguments being those that were passed to +\fBnext\fR). +.IP [4] +The result from the overall method call is the result from the outermost +method implementation; inner method implementations return their results +through \fBnext\fR. +.IP [5] +The method chain is cached for future use. +.SS "METHOD SEARCH ORDER" +.PP +When constructing the method chain, method implementations are searched for in +the following order: +.IP [1] +In the object. +.IP [2] +In the classes mixed into the object, in class traversal order. The list of +mixins is checked in natural order. +.IP [3] +In the classes mixed into the classes of the object, with sources of mixing in +being searched in class traversal order. Within each class, the list of mixins +is processed in natural order. +.IP [4] +In the object's class. +.IP [5] +In the superclasses of the class, following each superclass in a depth-first +fashion in the natural order of the superclass list. +.PP +Any particular method implementation always comes as \fIlate\fR in the +resulting list of implementations as possible. +.SS FILTERS +.PP +When an object has a list of filter names set upon it, or is an instance of a +class (or has mixed in a class) that has a list of filter names set upon it, +before every invocation of any method the filters are processed. Filter +implementations are found in class traversal order, as are the lists of filter +names (each of which is traversed in natural list order). Explicitly invoking +a method used as a filter will cause that method to be invoked twice, once as +a filter and once as a normal method. +.PP +Each filter should decide for itself whether to permit the execution to go +forward to the proper implementation of the method (which it does by invoking +the \fBnext\fR command as filters are inserted into the front of the method +call chain) and is responsible for returning the result of \fBnext\fR. +.PP +Filters are not invoked when processing an invocation of the \fBunknown\fR +method because of a failure to locate a method implementation, or when +invoking either constructors or destructors. +.SH EXAMPLES +.PP +This example demonstrates how to use the \fBnext\fR command to call the +(super)class's implementation of a method. The script: +.PP +.CS +oo::class create theSuperclass { + method example {args} { + puts "in the superclass, args = $args" + } +} +oo::class create theSubclass { + superclass theSuperclass + method example {args} { + puts "before chaining from subclass, args = $args" + \fBnext\fR a {*}$args b + \fBnext\fR pureSynthesis + puts "after chaining from subclass" + } +} +theSubclass create obj +oo::define obj method example args { + puts "per-object method, args = $args" + \fBnext\fR x {*}$args y + \fBnext\fR +} +obj example 1 2 3 +.CE +.PP +prints the following: +.PP +.CS +per-object method, args = 1 2 3 +before chaining from subclass, args = x 1 2 3 y +in the superclass, args = a x 1 2 3 y b +in the superclass, args = pureSynthesis +after chaining from subclass +before chaining from subclass, args = +in the superclass, args = a b +in the superclass, args = pureSynthesis +after chaining from subclass +.CE +.PP +This example demonstrates how to build a simple cache class that applies +memoization to all the method calls of the objects it is mixed into, and shows +how it can make a difference to computation times: +.PP +.CS +oo::class create cache { + filter Memoize + method Memoize args { + \fI# Do not filter the core method implementations\fR + if {[lindex [self target] 0] eq "::oo::object"} { + return [\fBnext\fR {*}$args] + } + + \fI# Check if the value is already in the cache\fR + my variable ValueCache + set key [self target],$args + if {[info exist ValueCache($key)]} { + return $ValueCache($key) + } + + \fI# Compute value, insert into cache, and return it\fR + return [set ValueCache($key) [\fBnext\fR {*}$args]] + } + method flushCache {} { + my variable ValueCache + unset ValueCache + \fI# Skip the caching\fR + return -level 2 "" + } +} + +oo::object create demo +oo::define demo { + mixin cache + method compute {a b c} { + after 3000 \fI;# Simulate deep thought\fR + return [expr {$a + $b * $c}] + } + method compute2 {a b c} { + after 3000 \fI;# Simulate deep thought\fR + return [expr {$a * $b + $c}] + } +} + +puts [demo compute 1 2 3] \fI\(-> prints "7" after delay\fR +puts [demo compute2 4 5 6] \fI\(-> prints "26" after delay\fR +puts [demo compute 1 2 3] \fI\(-> prints "7" instantly\fR +puts [demo compute2 4 5 6] \fI\(-> prints "26" instantly\fR +puts [demo compute 4 5 6] \fI\(-> prints "34" after delay\fR +puts [demo compute 4 5 6] \fI\(-> prints "34" instantly\fR +puts [demo compute 1 2 3] \fI\(-> prints "7" instantly\fR +demo flushCache +puts [demo compute 1 2 3] \fI\(-> prints "7" after delay\fR +.CE +.SH "SEE ALSO" +oo::class(n), oo::define(n), oo::object(n), self(n) +.SH KEYWORDS +call, method, method chain +.\" Local variables: +.\" mode: nroff +.\" fill-column: 78 +.\" End: |