class(n)
π NAME π
bestie, welcome to class(n) from [incr Tcl] β this page is literally about itcl::class β create a class of objects π«Ά
β¨ SYNOPSIS β¨
itcl::class className {
inherit baseClass ?baseClass...?
constructor args ?init? body
destructor body
method name ?args? ?body?
proc name ?args? ?body?
variable varName ?init? ?config?
common varName ?init?
public command ?arg arg ...?
protected command ?arg arg ...?
private command ?arg arg ...?
set varName ?value?
array option ?arg arg ...?
}
className objName ?arg arg ...?
objName method ?arg arg ...?
className::proc ?arg arg ...?
π¦ DESCRIPTION π¦
okay so the fundamental construct in [incr Tcl] is the class definition. each class acts as a template for actual objects that can be created. the class itself is a namespace which contains things common to all objects. each object has its own unique bundle of data which contains instances of the variables defined in the class definition. each object also has a built-in variable named this, which contains the name of the object. classes can also have common data members that are shared by all objects in a class. π
two types of functions can be included in the class definition, and yes they are giving very different energy:
- Methods are functions which operate on a specific object, and therefore have access to both
variablesandcommondata members. π - Procs are ordinary procedures in the class namespace, and only have access to
commondata members. π
if the body of any method or proc starts with @, it is treated as the symbolic name for a C procedure. otherwise, it is treated as a Tcl code script. see below for details on registering and using C procedures. π§
β οΈ a class can only be defined once, although the bodies of class methods and procs can be defined again and again for interactive debugging. see thebodyandconfigbodycommands for details. no cap, that part matters.
each namespace can have its own collection of objects and classes. the list of classes available in the current context can be queried using the itcl::find classes command, and the list of objects, with the itcl::find objects command. π
a class can be deleted using the delete class command. individual objects can be deleted using the delete object command. periodt. π
π CLASS DEFINITIONS π
okay bestie, this is the β¨birthβ¨ section β where a class actually comes into existence.
classclassName definition β this is the whole vibe: it provides the definition for a class named className. If className already exists, or if there's already a command called className chilling in the current namespace context, this command returns an error (sorry π). But if the class definition parses cleanly, className becomes a command in the current context, and that command is the one handling the creation of objects for this class. main character energy, fr.
The class definition is evaluated as a series of Tcl statements that define elements within the class. These are the class definition commands it recognizes β buckle up π
𧬠inherit baseClass ?baseClass...?
Causes the current class to inherit characteristics from one or more base classes. Those classes must have been defined by a previous class command, or must be available to the auto-loading facility (see "AUTO-LOADING" below π). And heads up: a single class definition can contain no more than one inherit command. one and done, periodt.
The order of the baseClass names in the inherit list totally affects name resolution for class members. When the same member name shows up in two or more base classes, the base class that appears first in the inherit list takes precedence. So like, if classes "Foo" and "Bar" both contain the member "x", and another class has this "inherit" statement:
inherit Foo Bar
then the name "x" means "Foo::x". Any other inherited members named "x" have to be referenced with their explicit name, like "Bar::x". no shortcuts, bestie π€·ββοΈ
ποΈ constructor args ?init? body
Declares the args argument list and body used for the constructor, which is automatically invoked whenever an object is created. it just happens, you don't call it.
Before the body is executed, the optional init statement is used to invoke any base class constructors that require arguments. Variables in the args specification can be accessed in the init code fragment, and passed to base class constructors. After evaluating the init statement, any base class constructors that have not been executed are invoked automatically without arguments. This ensures all base classes are fully constructed before the constructor body is executed. iconic, honestly π«Ά
By default, this scheme causes constructors to be invoked in order from least- to most-specific. Which is exactly the opposite of the order that classes are reported by the info heritage command. yes, they really did that π
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 current namespace context. If construction fails, an error message is returned. simple as that.
π destructor body
Declares the body used for the destructor, which is automatically invoked when 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 interpreter. If destruction fails, an error message is returned and the object remains. it's giving "you can't get rid of me that easily" π
When an object is destroyed, all destructors in its class hierarchy are invoked in order from most- to least-specific. That's the order the classes are reported by the "info heritage" command, and it's exactly the opposite of the default constructor order. so yes: constructors build outside-in, destructors tear down inside-out. symmetry, we love to see it π
π οΈ method name ?args? ?body?
Declares a method called name. When the method body is executed, it will have automatic access to object-specific variables and common data members. no passing stuff around like a peasant β¨
If the args list is specified, it establishes the usage information for this method. The body command can be used to redefine the method body, but the args list must match this specification. no swapping the vibe halfway through.
Within the body of another class method, a method can be invoked like any other command β simply by using its name. Outside of the class context, the method name must be prefaced with an object name, which provides the context for the data that it manipulates. Methods in a base class that are redefined in the current class, or hidden by another base class, can be qualified using the "className::method" syntax. iykyk π¦
π§ proc name ?args? ?body?
Declares a proc called name. A proc is an ordinary procedure within the class namespace. Unlike a method, a proc is invoked without referring to a specific object. When the proc body is executed, it will have automatic access only to common data members. so no object-specific data for you, bestie, that's the rule πΈ
If the args list is specified, it establishes the usage information for this proc. The body command can be used to redefine the proc body, but the args list must match this specification.
Within the body of another class method or proc, a proc can be invoked like any other command β simply by using its name. In any other namespace context, the proc is invoked using a qualified name like "className::proc". Procs in a base class that are redefined in the current class, or hidden by another base class, can also be accessed via their qualified name. sure, queen, gatekeep your procs π
π variable varName ?init? ?config?
Defines an object-specific variable named varName. All object-specific variables are automatically available in class methods. They don't need to be declared with anything like the global command. imagine that. freedom.
If the optional init string is specified, it's 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 set within the constructor and used as arrays. know the difference π₯
The optional config script is only allowed for public variables. If specified, this code fragment is executed whenever a public variable is modified by the built-in "configure" method. The config script can also be specified outside of the class definition using the configbody command. flexible king π
π common varName ?init?
Declares a common variable named varName. Common variables reside in the class namespace and are shared by all objects belonging to the class. They're just like global variables, except they don't need to be declared with the usual global command. They're automatically visible in all class methods and procs. communal vibes π
If the optional init string is specified, it's 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 set with subsequent set and array commands and used as arrays.
Once a common data member has been defined, it can be set using set and array commands within the class definition. This allows common data members to be initialized as arrays. for example:
itcl::class Foo {
common boolean
set boolean(true) 1
set boolean(false) 0
}
β οΈ note that if common data members are initialized within the constructor, they get initialized again and again whenever new objects are created. so, like, don't do that unless you're obsessed with redundant work π
π public command ?arg arg ...?
π protected command ?arg arg ...?
π private command ?arg arg ...?
These three besties are used to set the protection level for class members that are created when command is evaluated. The command is usually method, proc, variable or common, and the remaining arg's complete the member definition.
But wait β command can also be a script containing many different member definitions, and the protection level will apply to all of the members that are created. bulk permissioning, no cap π
πΈ CLASS USAGE πΈ
Once a class has been defined, the class name can be used as a command to create new objects belonging to the class. yes, the class name is literally a command now. slay.
className objName ?args...?β creates a new object in class className with the name objName. The remaining arguments are passed to the constructor of the most-specific class. That in turn passes arguments to base class constructors before invoking its own body of commands. If construction is successful, a command called objName is created in the current namespace context, and objName is returned as the result of this operation. If an error is encountered during construction, the destructors are automatically invoked to free any resources that have been allocated, the object is deleted, and an error is returned. clean-up crew stays winning π§Ή
If objName contains the string "#auto", that string is replaced with an automatically generated name. Names have the form className<number>, where the className part is modified to start with a lowercase letter. In class "Toaster", for example, the "#auto" specification would produce names like toaster0, toaster1, etc. π
Note that "#auto" can also be buried within an object name:
fileselectiondialog .foo.bar.#auto -background red
This would generate an object named .foo.bar.fileselectiondialog0. it's giving "pick me, choose me" energy π
π¦ OBJECT USAGE π¦
Once an object has been created, the object name can be used as a command to invoke methods that operate on the object. your object has a name and it will be used.
objName method ?args...?β invokes a method named method on an object named objName. The remaining arguments are passed to the argument list for 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.
β¨ BUILT-IN METHODS β¨
okay so every object comes with these built-in baddies, and they are literally the blueprint of class usage π
objName cget option
this one gives you access to public variables as configuration options, no cap. it mimics the usual cget operation for Tk widgets. the option argument is a string like -varName, and this method returns the current value of the public variable varName. cute, simple, iconic β¨
objName configure ?option? ?value option value ...?
also gives you access to public variables as configuration options, and it mimics the usual configure operation for Tk widgets π
with no arguments, this method returns a list of lists describing all of the public variables. each list has three elements: the variable name, its initial value and its current value. yes bestie, all three, every time π
if a single option of the form -varName is specified, then this method returns the information for that one variable.
otherwise, the arguments are treated as option/value pairs assigning new values to public variables. each variable is assigned its new value, and if it has any config code associated with it, that code is executed in the context of the class where it was defined. and if the config code generates an error, the variable is set back to its previous value, and the configure method returns an error. dramatic? maybe. safe? absolutely π«Ά
objName isa className
returns non-zero if the given className can be found in the object's heritage, and zero otherwise. simple vibe check, honestly π
objName info option ?args...?
returns information related to a particular object named objName, or to its class definition. the option parameter includes the following things, as well as the options recognized by the usual Tcl info command:
objName info classβ returns the name of the most-specific class for objectobjNameπobjName info inheritβ returns the list of base classes as they were defined in theinheritcommand, or an empty string if this class has no base classes.objName info heritageβ returns the current class name and the entire list of base classes in the order that they are traversed for member lookup and object destruction.objName info function ?cmdName? ?-protection? ?-type? ?-name? ?-args? ?-body?β with no arguments, this command returns a list of all class methods and procs. ifcmdNameis specified, it returns information for a specific method or proc. if no flags are specified, this command returns a list with the following elements: the protection level, the type (method/proc), the qualified name, the argument list and the body. flags can be used to request specific elements from this list.objName info variable ?varName? ?-protection? ?-type? ?-name? ?-init? ?-value? ?-config? ?-scope?β with no arguments, this command returns a list of all object-specific variables and common data members. ifvarNameis specified, it returns information for a specific data member. flags can be specified withvarNamein an arbitrary order. the result is a list of the specific information in exactly the same order as the flags are specified.
if no flags are given for objName info variable, this command returns a list as if the following flags have been specified:
-protection -type -name -init -value ?-config?
the -config result is only present if varName is a public variable. it contains the code that is executed at initialization of varName. the -scope flag gives the namespace context of varName. herewith the variable can be accessed from outside the object like any other variable. it is similar to the result of the itcl::scope command. little bit magical, honestly π§
π§ CHAINING METHODS/PROCS π§
sometimes a base class has a method or proc that is redefined with the same name in a derived class. this is a way of making the derived class handle the same operations as the base class, but with its own specialized behavior. so like, same name, new personality β¨
for example, suppose we have a Toaster class that looks like this:
itcl::class Toaster {
variable crumbs 0
method toast {nslices} {
if {$crumbs > 50} {
error "== FIRE! FIRE! =="
}
set crumbs [expr {$crumbs+4*$nslices}]
}
method clean {} {
set crumbs 0
}
}
we might create another class like SmartToaster that redefines the toast method. if we want to access the base class method, we can qualify it with the base class name, to avoid ambiguity:
itcl::class SmartToaster {
inherit Toaster
method toast {nslices} {
if {$crumbs > 40} {
clean
}
return [Toaster::toast $nslices]
}
}
instead of hard-coding the base class name, we can use the chain command like this:
itcl::class SmartToaster {
inherit Toaster
method toast {nslices} {
if {$crumbs > 40} {
clean
}
return [chain $nslices]
}
}
the chain command searches through the class hierarchy for a slightly more generic (base class) implementation of a method or proc, and invokes it with the specified arguments. it starts at the current class context and searches through base classes in the order that they are reported by the info heritage command. if another implementation is not found, this command does nothing and returns the null string. no notes, bestie π
π¦ AUTO-LOADING π¦
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. it's giving organized folder behavior π
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, version 2.0 for [incr Tcl]
# This file is generated by the "auto_mkindex" command
# and sourced to set up indexing information for one or
# more commands. Typically each line is a command that
# sets an element in the auto_index array, where the
# element name is the name of a command and the value is
# a script that loads the command.
set auto_index(::Toaster) "source $dir/Toaster.itcl"
set auto_index(::SmartToaster) "source $dir/SmartToaster.itcl"
the auto_mkindex command is used to automatically generate tclIndex files.
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. lazy loading but make it classy, periodt π
π C PROCEDURES π
C procedures can be integrated into an [incr Tcl] class definition to implement methods, procs, and the config code for public variables. any body that starts with @ is treated as the symbolic name for a C procedure. yes, an actual crossover episode π
symbolic names are established by registering procedures via Itcl_RegisterObjC(). this is usually done in the Tcl_AppInit() procedure, which is automatically called when the interpreter starts up. in the following example, the procedure My_FooObjCmd() is registered with the symbolic name "foo". this procedure can be referenced in the body command as "@foo".
int
Tcl_AppInit(interp)
Tcl_Interp *interp; /* Interpreter for application. */
{
if (Itcl_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
}
if (Itcl_RegisterObjC(interp, "foo", My_FooObjCmd) != TCL_OK) {
return TCL_ERROR;
}
}
C procedures are implemented just like ordinary Tcl commands. see the CrtCommand man page for details. within the procedure, class data members can be accessed like ordinary variables using Tcl_SetVar(), Tcl_GetVar(), Tcl_TraceVar(), etc. class methods and procs can be executed like ordinary commands using Tcl_Eval(). [incr Tcl] makes this possible by automatically setting up the context before executing the C procedure. it's lowkey doing so much behind the scenes π«Ά
this scheme provides a natural migration path for code development. classes can be developed quickly using Tcl code to implement the bodies. an entire application can be built and tested. when necessary, individual bodies can be implemented with C code to improve performance. start cute, optimize later, iykyk π
π KEYWORDS π
classobjectobject-oriented
and that's the whole page, bestie π source/version: itcl; page: class(n); date: the footer's date slot is literally empty, so it's giving timeless icon behavior β¨ππ¦
π¦ where this page comes from
- alpine 3.23: tcl-doc 8.6.17-r0 Β· TCL
- alpine 3.23: tcl9-doc 9.0.3-r0 Β· TCL
- alpine 3.24: tcl-doc 8.6.17-r1 Β· TCL
- alpine 3.24: tcl9-doc 9.0.3-r2 Β· TCL
- nixos 26.05: tcl 9.0.3
- nixpkgs unstable: tcl 9.1.0
- Copyright (c) 1993-1998 Lucent Technologies, Inc
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms