209 lines
7.5 KiB
Plaintext
209 lines
7.5 KiB
Plaintext
'\"
|
|
'\" 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.
|
|
'\"
|
|
.TH next n 0.1 TclOO "TclOO Commands"
|
|
.so man.macros
|
|
.BS
|
|
'\" Note: do not modify the .SH NAME line immediately below!
|
|
.SH NAME
|
|
next, nextto \- 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 classes mixed into the object, in class traversal order. The list of
|
|
mixins is checked in natural order.
|
|
.IP [2]
|
|
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 [3]
|
|
In the object itself.
|
|
.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; this means that if some class,
|
|
A, is both mixed into a class, B, and is also a superclass of B, the instances
|
|
of B will always treat A as a superclass from the perspective of inheritance.
|
|
This is true even when the multiple inheritance is processed indirectly.
|
|
.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 invoked when processing an invokation of the \fBunknown\fR
|
|
method because of a failure to locate a method implementation, but \fInot\fR
|
|
when invoking either constructors or destructors. (Note however that the
|
|
\fBdestroy\fR method is a conventional method, and filters are invoked as
|
|
normal when it is called.)
|
|
.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::objdefine 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::objdefine 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:
|