incrTcl(3Tcl) incrTcl(3Tcl)
incrTcl - Object-oriented extensions to Tcl
itcl_class className {
inherit baseClass ?baseClass...?
constructor args body
destructor body
method name args body
proc name args body
public varName ?init? ?config?
protected varName ?init?
common varName ?init?
}
className objName ?args...?
className #auto ?args...?
className :: proc ?args...?
objName method ?args...?
itcl_info classes ?pattern?
itcl_info objects ?pattern? ?-class className? ?-isa className?
Commands available within class methods/procs:
global varName ?varName...?
previous command ?args...?
virtual command ?args...?
[incr Tcl] provides object-oriented extensions to Tcl, much as C++
provides object-oriented extensions to C. The emphasis of this work,
however, is not to create a whiz-bang object-oriented programming
environment. Rather, it is to support more structured programming
practices in Tcl without changing the flavor of the language. More than
anything else, [incr Tcl] provides a means of encapsulating related
procedures together with their shared data in a local namespace that is
hidden from the outside world. It encourages better programming by
promoting the object-oriented "library" mindset. It also allows for code
re-use through inheritance.
The fundamental construct in [incr Tcl] is the class definition. Each
class acts as a template for actual objects that can be created. Each
object in a class contains a unique bundle of data, including "public"
and "protected" data members. When execution takes place within the
scope of the class, both types of data members are accessible. To the
programmer working outside of the class scope-using an object to build
his application-only public data members are accessible. Public members
represent attributes that can be used to configure an object. For
example, the "-text" attribute in the usual Tk "button" widget could be
Page 1
incrTcl(3Tcl) incrTcl(3Tcl)
thought of as a public member. Protected members, on the other hand,
reflect the inner workings of an object and are kept hidden from the
outside world. This insulates the programmer that uses a class from the
details of its implementation. Classes can also define "common" data
members that are shared by all objects in a class. Like protected
members, common members are only accessible within the scope of the
class. The class designer will often provide special class-level
procedures or "procs" to manipulate common members. Since these "procs"
can be invoked without reference to any specific object, they have access
to common members, but not to public or protected members.
Special procedures called "methods" are used to manipulate individual
objects. The use of methods should be familiar to any Tk programmer-the
"button" widget, for example, has methods such as "flash" and "invoke"
that are used to control its behavior. These methods form a contract
between the class designer and the application developer, completely
specifying the list of functions that can be used to interact with
objects in the class. The implementation details within each method,
however, are left solely to the class designer. The public interface
says what an object will do but not how it will do it. Insulating the
application developer from these details leaves the class designer free
to change them at any time, without warning, and without affecting
programs that rely on the class. It is precisely this encapsulation that
makes object-oriented programs easier to understand and maintain.
The fact that [incr Tcl] objects look like Tk widgets is no accident.
[incr Tcl] was designed this way, to blend naturally into a Tcl/Tk
application. But [incr Tcl] extends the Tk paradigm from being merely
object-based to being fully object-oriented. An object-oriented system
supports inheritance, allowing classes to share common behaviors by
inheriting them from an ancestor or base class. Having a base class as a
common abstraction allows a programmer to treat related classes in a
similar manner. For example, a toaster and a blender perform different
(specialized) functions, but both share the abstraction of being
appliances. By abstracting common behaviors into a base class, code can
be shared rather than copied. The resulting application is easier to
understand and maintain, and derived classes (e.g., specialized
appliances) can be added or removed more easily.
This description was merely a brief overview of object-oriented
programming and [incr Tcl]. A more tutorial introduction is presented in
the paper included with this distribution. Further details are presented
in reference form below.
Each class maintains its own local scope, separate from the main
interpreter. Within the scope of a class, all members-including methods
and procs, as well as public, protected and common variables-can be
accessed transparently. In other words, methods and procs can be used
like ordinary commands, and variables can be used without declaring them
with anything like the Tcl "global" command.
Page 2
incrTcl(3Tcl) incrTcl(3Tcl)
The scope of a class extends to all derived classes as well, so members
can be accessed transparently throughout a derivation hierarchy. If the
same member name appears more than once in the hierarchy, the class with
highest priority gets transparent access to the simple member name, and
all other members must be accessed using the explicit "class::member"
syntax. Priority is determined by the list of classes as reported by the
"info heritage" command.
If a command is not recognized in a particular class scope, it is passed
up the derivation hierarchy for evaluation. Again, base classes are
consulted in the order reported by the "info heritage" command. If a
command is not recognized by any class in the hierarchy, it is passed out
to the global scope (main interpreter) for evaluation. This scheme
allows Tk widget commands, for example, to be accessed transparently
within any class, but to be executed (as they should be) in the global
scope. Any command can be sent explicitly to the global scope using the
"::command" syntax.
It is sometimes convenient, particularly when dealing with Tk widgets, to
have access to global variables that exist in the main interpreter. This
is achieved using the usual Tcl "global" command within a class method or
proc.
Class methods and procs look like ordinary Tcl procs, except that they
also provide transparent access to class data. The rules for handling
formal arguments in the args lists are the same as well. Each element of
this list can be a simple argument name, or another list containing the
argument name and its default value. If the last formal argument is
named "args", it will absorb all unmatched arguments into a single list
of values.
Argument lists for class methods also recognize a special argument to
handle configuration of public variables. If the last formal argument is
named "config", it will absorb all unmatched arguments and parse them as
"-varName value" assignments. If varName is recognized as a public
variable, then this variable is modified to contain the given value. If
the variable was defined with special config code, this code is
automatically executed in the scope of its associated class. If this
config code returns an error, the variable is automatically reset to its
previous value, and the method is aborted, returning the configuration
error. If argument parsing is successful, the "config" variable is set
to the list of variables that were configured, and the method body is
executed.
As an example, suppose that we define a simple class with two public
variables:
itcl_class Thing {
constructor {config} {}
method configure {config} {}
Page 3
incrTcl(3Tcl) incrTcl(3Tcl)
public foo "" { puts stdout "-- just modified foo: $foo" }
public bar "" { puts stdout "-- just modified bar: $bar" }
}
Both the constructor and the "configure" method contain the special
"config" formal argument. Thus, either of these methods can be used to
configure the public variables:
wish: Thing x -foo 1 -bar 2
-- just modified foo: 1
-- just modified bar: 2
x
wish: x configure -bar 3
-- just modified bar: 3
Each time "foo" or "bar" is configured in this example, its special
config code (last argument in the "public" declaration) is executed,
printing a message to show the updated value.
itcl_class className definition
Provides the definition for a class named className. If className
is already defined, then this command returns an error. If the
class definition is successfully parsed, className becomes a command
in the interpreter, handling the creation of objects and providing
access to class scope. The class definition is evaluated as a
series of Tcl statements that configure the interpreter managing a
particular class scope. In addition to the usual commands, the
following class definition commands are recognized:
inherit baseClass ?baseClass...?
Declares one or more base classes, causing the current class to
inherit their characteristics. Classes must have been defined
by a previous "itcl_class" command, or must be available to the
auto-loading facility (see "AUTO-LOADING" below). A single
class definition can contain no more than one "inherit"
command.
When the same member name appears in two or more base classes,
the base class that appears first in the "inherit" list takes
precedence. For example, if classes "Foo" and "Bar" both
contain the member "x", then the "inherit" statement:
inherit Foo Bar
allows "Foo::x" to be accessed simply as "x" but forces
"Bar::x" (and all other inherited members named "x") to be
referenced with their explicit "class::member" name.
constructor args body
Declares the argument list and body used for the constructor,
which is automatically invoked whenever an object is created.
If construction is successful, the constructor always returns
the object name-regardless of how the body is defined-and the
object name becomes a command in the main interpreter. If
construction fails, an error message is returned.
Page 4
incrTcl(3Tcl) incrTcl(3Tcl)
Like any other method, the constructor can be inherited from a
base class. Furthermore, any base class constructor that is
not explicitly invoked within body will be implicitly invoked
by [incr Tcl] in the order that the base classes are reported
in the "info heritage" command. This ensures that all base
classes are properly constructed.
destructor body
Declares the body used for the destructor, which is
automatically invoked whenever an object is deleted. If the
destructor is successful, the object data is destroyed and the
object name is removed as a command from the main interpreter.
If destruction fails, an error message is returned and the
object remains.
Like any other method, the destructor can be inherited from a
base class. Furthermore, any base class destructor that is not
explicitly invoked within body will be implicitly invoked by
[incr Tcl], in the reverse order compared to constructors.
method name args body
Declares a method called name with an argument list args and a
body of Tcl statements. A method is just like the usual Tcl
"proc" except that it has transparent access to public,
protected and common variables. Within the class scope, a
method can be invoked like any other command-simply by using
its name. In the external interpreter, the method name must be
prefaced by an object name. Methods in a base class that are
redefined in the current class or hidden by another base class
can be explicitly scoped using the "class::method" syntax.
proc name args body
Declares a proc called name with an argument list args and a
body of Tcl statements. A proc is similar to a method, except
that it can be invoked without referring to a specific object,
and therefore has access only to common variables-not to public
or protected variables. Within the class scope, a proc can be
invoked like any other command-simply by using its name. In
the external interpreter, the proc is invoked using the
className command "className :: proc" to access the class scope
(see below). Procs in a base class that are redefined in the
current class or hidden by another base class can be explicitly
scoped using the "class::proc" syntax.
public varName ?init? ?config?
Declares a public variable named varName. Public variables are
visible in methods within the scope of their class and any
derived class. In addition, they can be modified outside of
the class scope using the special "config" formal argument (see
"ARGUMENT LISTS" above). If the optional init is specified, it
is used as the initial value of the variable when a new object
is created. If the optional config command is specified, it is
Page 5
incrTcl(3Tcl) incrTcl(3Tcl)
invoked whenever a public variable is modified via the "config"
formal argument; if the config command returns an error, the
public variable is reset to its value before configuration, and
the method handling the configuration returns an error.
protected varName ?init?
Declares a protected variable named varName. Protected
variables are visible in methods within the scope of their
class and any derived class, but cannot be modified outside of
the class scope. If the optional init is specified, it is used
as the initial value of the variable when a new object is
created. Initialization forces the variable to be a simple
scalar value; uninitialized variables, on the other hand, can
be used as arrays. All objects have a built-in protected
variable named "this" which is initialized to the instance name
for the object.
common varName ?init?
Declares a common variable named varName. Common variables are
shared among all objects in a class. They are visible in
methods and procs in the scope of their class and any derived
class, but cannot be modified outside of the class scope. If
the optional init is specified, it is used as the initial value
of the variable. Initialization forces the variable to be a
simple scalar value; uninitialized variables, on the other
hand, can be used as arrays.
Once a common variable has been declared, it can be configured
using ordinary Tcl code within the class definition. This
facility is particularly useful when the initialization of the
variable is non-trivial - when the variable contains an array
of values, for example:
itcl_class Foo {
.
.
common boolean
set boolean(true) 1
set boolean(false) 0
}
When a class definition has been loaded (or made available to the autoloader),
it can be used as a command in the main interpreter:
className objName ?args...?
Creates a new object in class className with the name objName.
Remaining arguments are passed to the constructor. If construction
is successful, the object name is returned and this name becomes a
command in the main interpreter. Otherwise, an error is returned.
Page 6
incrTcl(3Tcl) incrTcl(3Tcl)
className #auto ?args...?
Creates a new object in class className with an automatically
generated name. Names are of the form className<number>, e.g.,
Toaster0, Toaster1, etc. Remaining arguments are passed to the
constructor. If construction is successful, the object name is
returned and this name becomes a command in the main interpreter.
Otherwise, an error is returned.
className :: proc ?args...?
Used at the global scope to invoke a class proc named proc. Class
procs are like ordinary Tcl procs, except that they are executed in
the scope of the class and therefore have transparent access to
common data members.
Notice that, unlike any other scope qualifier in [incr Tcl], the
"::" shown above is surrounded by spaces. This is necessary to
avoid polluting the global namespace with every possible
"class::proc" command. In Release 1.1, a special version of the |
usual "unknown" proc was provided to recognize commands like |
"class::proc" (without spaces around the "::" qualifier). This |
facility was unpopular, and is no longer supported. When class |
procs are invoked from the main interpreter, the "::" qualifier must|
be surrounded by spaces.
objName method ?args...?
Invokes a method named method to operate on the specified object.
Remaining arguments are passed to the method. The method name can
be "constructor", "destructor", any method name appearing in the
class definition, or any of the following built-in methods.
objName isa className
Returns non-zero if the given className can be found in the object's
heritage, and zero otherwise.
objName delete
Invokes the destructor associated with an object. If the destructor
is successful, data associated with the object is deleted and
objName is removed from the commands in the main interpreter.
Returns the empty string, regardless of the destructor body.
objName info option ?args...?
className :: info option ?args...?
Returns information related to the class definition, or information
concerning the interpreter that implements the class scope. The
option parameter includes the following things, as well as the
options recognized by the usual Tcl "info" command:
Page 7
incrTcl(3Tcl) incrTcl(3Tcl)
objName info class
Returns the class name at the current class scope. When
prefaced by the object name, this command executes in the
most-specific class scope, and therefore returns the mostspecific
class name.
objName info inherit
Returns the list of base classes as they were defined in the
"inherit" command, or an empty string if this is a top-level
class.
objName info heritage
Returns the current class name and the entire list of base
classes in the order that they are traversed for object
construction or member lookup.
objName info method
objName info method methodName ?-args? ?-body?
In the first form, this command returns a list of all class
methods. In the second form, it returns information for a
specific method. If neither of the optional -args or -body
flags is specified, a complete method definition is returned as
a list of three elements including the method name, argument
list and body. Otherwise, the requested information is
returned without the method name. If the methodName is not
recognized, an empty string is returned.
objName info proc
objName info proc procName ?-args? ?-body?
In the first form, this command returns a list of all class
procs. In the second form, it returns information for a
specific proc. If neither of the optional -args or -body flags
is specified, a complete proc definition is returned as a list
of three elements including the proc name, argument list and
body. Otherwise, the requested information is returned without
the proc name. If the procName is not recognized, an empty
string is returned.
objName info public
objName info public varName ?-init? ?-value? ?-config?
In the first form, this command returns a list of all public
variables. In the second form, it returns information for a
specific public variable. If none of the optional -init,
-value or -config flags are specified, all available
information is returned as a list of four elements including
the variable name, initial value, current value, and
configuration commands. Otherwise, the requested information
is returned without the variable name. If the varName is not
recognized, an empty string is returned.
Page 8
incrTcl(3Tcl) incrTcl(3Tcl)
objName info protected
objName info protected varName ?-init? ?-value?
In the first form, this command returns a list of all protected
variables. In the second form, it returns information for a
specific protected variable. If neither of the optional -init
or -value flags is specified, all available information is
returned as a list of three elements including the variable
name, initial value and current value. Otherwise, the
requested information is returned without the variable name.
If the varName is not recognized, an empty string is returned.
objName info common
objName info common varName ?-init? ?-value?
In the first form, this command returns a list of all common
variables. In the second form, it returns information for a
specific common variable. If neither of the optional -init or
-value flags is specified, all available information is
returned as a list of three elements including the variable
name, initial value and current value. Otherwise, the
requested information is returned without the variable name.
If the varName is not recognized, an empty string is returned.
CLASS/OBJECT INFORMATION
The following commands are available at the global scope to query
information about classes and objects that have been created.
itcl_info classes ?pattern?
Returns a list of classes with names matching the string pattern
according to the rules of the "string match" command. If pattern is
not specified, returns a list of all known classes.
itcl_info objects ?pattern? ?-class className? ?-isa className?
Returns a list of objects with names matching the string pattern
according to the rules of the "string match" command. If pattern is
not specified, return a list of all known objects. If the "-class"
parameter is specified, this list is restricted to objects whose
most-specific class is className. If the "-isa" parameter is
specified, this list is further restricted to objects having the
given className anywhere in their heritage.
OTHER BUILT-IN COMMANDS [Toc] [Back] The following commands are also available within the scope of each class.
They cannot be accessed from outside of the class as proper methods or
procs; rather, they are useful inside the class when implementing its
functionality.
global varName ?varName...?
Creates a link to one or more global variables in the main
interpreter. This is useful when communicating with Tk widgets that
rely on global variables.
Page 9
incrTcl(3Tcl) incrTcl(3Tcl)
previous command ?args...?
Invokes command in the scope of the most immediate base class (i.e.,|
the "previous" class) for the object. For classes using single
inheritance, this facility can be used to avoid hard-wired base
class references of the form "class::command", making code easier to
maintain. For classes using multiple inheritance, the utility of
this function is dubious. If the class at the relevant scope has no
base class, an error is returned.
virtual command ?args...?
Invokes command in the scope of the most-specific class for the |
object. This provides a way of accessing "virtual" functions from |
within class methods. Normally, the commands at a certain class |
scope refer to methods/procs in that class or in less-specific base |
classes upward in the hierarchy. The virtual command moves the |
scope downward to the most-specific class in the hierarchy, and then|
invokes the method. If a class has methods that are redefined in |
derived classes, this causes the most-specific method to be invoked.|
Note that this is only needed when commands are invoked from within |
a class; when commands are invoked at the global scope, they are |
automatically executed in the scope of the most-specific class.
Class definitions need not be loaded explicitly; they can be loaded as
needed by the usual Tcl auto-loading facility. Each directory containing
class definition files should have an accompanying "tclIndex" file. Each
line in this file identifies a Tcl procedure or [incr Tcl] class
definition and the file where the definition can be found.
For example, suppose a directory contains the definitions for classes
"Toaster" and "SmartToaster". Then the "tclIndex" file for this
directory would look like:
# Tcl autoload index file: each line identifies a Tcl
# procedure or [incr Tcl] class and the file where that
# entity is defined.
Toaster Toaster.tcl
SmartToaster SmartToaster.tcl
The auto-loader must be made aware of this directory by appending the
directory name to the "auto_path" variable. When this is in place,
classes will be auto-loaded as needed when used in an application.
Note: the usual "auto_mkindex" procedure used to generate the "tclIndex"
file does not, by default, recognize [incr Tcl] class definitions;
however, it can be modified to do so. Such a modification is included in
the "library" directory in the usual distribution for [incr Tcl].
object-oriented, class
PPPPaaaaggggeeee 11110000 [ Back ]
|