summaryrefslogtreecommitdiffstats
path: root/doc/next.n
diff options
context:
space:
mode:
Diffstat (limited to 'doc/next.n')
-rw-r--r--doc/next.n203
1 files changed, 203 insertions, 0 deletions
diff --git a/doc/next.n b/doc/next.n
new file mode 100644
index 0000000..8eb2ba6
--- /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 invokation 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 invokation 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 superclassm 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 cacheing\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: