extendedclass(3itcl)
π extendedclass(3itcl) β the [incr Tcl] era π
okay bestie, gather round, because we're about to talk about itcl::extendedclass β yes, that extendedclass from the 3itcl manual, she's iconic, she's giving template energy, and she's about to become your whole personality. π¦
β οΈ WARNING! This is new functionality in [incr Tcl] where the API can still change!! Like, she's still figuring herself out, okay? Don't build your whole life on her yet. π
β¨ SYNOPSIS β¨
itcl::extendedclass extendedclassName {
inherit baseExtendedclass ?baseExtendedclass...?
constructor args ?init? body
destructor body
public method name ?args? ?body?
protected method name ?args? ?body?
private method name ?args? ?body?
public proc name ?args? ?body?
protected proc name ?args? ?body?
private proc name ?args? ?body?
public variable varName ?init? ?config?
protected variable varName ?init? ?config?
private variable varName ?init? ?config?
public common varName ?init?
protected common varName ?init?
private common varName ?init?
public command ?arg arg ...?
protected command ?arg arg ...?
private command ?arg arg ...?
<delegation info> see delegation page
<option info> see option page
set varName ?value?
array option ?arg arg ...?
}
extendedclassName objName ?arg arg ...?
objName method ?arg arg ...?
extendedclassName::proc ?arg arg ...?
πΈ DESCRIPTION πΈ
okay so the whole fundamental construct in [incr Tcl] β the main character, the blueprint, the moment β is the extendedclass definition. π Every single extendedclass is literally a template for actual objects you can create. She's not just a vibe, she's a whole structure.
The extendedclass itself is a namespace which contains things common to all objects. And every object gets its own unique little bundle of data β its own instances of the "variables" defined in the extendedclass definition. So like, same template, different data, you feel me? π
Every object also has a built-in variable named this, which contains the name of the object. yes, this. she's always there. she knows her name. self-aware queen. β¨
Extendedclasses can also have "common" data members that are shared by all objects in a extendedclass. shared. communal. the group chat of data. π«Ά
two types of functions, bestie
Two types of functions can be included in the extendedclass definition, and ngl the difference matters:
- "Methods" β functions which operate on a specific object, and therefore have access to both "variables" and "common" data members. so they see everything. nosy in a useful way. π
- "Procs" β ordinary procedures in the extendedclass namespace, and only have access to "common" data members. they don't get the private tea. respect the boundaries. π
the "@" thing, lowkey important
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. so yeah, that one character changes everything. iconic behavior honestly. π
one definition, but the bodies are flexible
A extendedclass can only be defined once, although the bodies of extendedclass methods and procs can be defined again and again for interactive debugging. See the body and configbody commands for details. so like, the skeleton is forever, but the outfit can be changed. slay. π₯
namespaces, objects, and finding your people
Each namespace can have its own collection of objects and extendedclasses. The list of extendedclasses available in the current context can be queried using the itcl::find extendedclasses command, and the list of objects, with the itcl::find objects command. like a little directory of everyone who exists. π
A extendedclass can be deleted using the delete extendedclass command. Individual objects can be deleted using the delete object command. and that's it, she's gone, no notes, periodt. π
okay that's part one bestie, hold on, there's more coming and we are NOT done yet π
π CLASS DEFINITIONS π
extendedclass extendedclassName definition
Okay bestie, this is THE one. It hands over the whole definition of an extendedclass named extendedclassName. π
But listen β if extendedclassName already exists, or if there's already a command called extendedclassName chilling in the current namespace context, this command returns an error. No duplicates, no take-backs, periodt. π
If the definition parses cleanly though? extendedclassName becomes a command in the current context, and that command is the one that handles creating objects for this extendedclass. Main character energy fr fr. π
The definition gets evaluated as a series of Tcl statements that define elements inside the extendedclass. The extendedclass definition commands that get recognized are:
inherit baseExtendedclass ?baseExtendedclass...?
Makes the current extendedclass inherit characteristics from one or more base extendedclasses. Those base extendedclasses have to have been defined by a previous extendedclass command already, or be available to the auto-loading facility (peep "AUTO-LOADING" below π). And heads up β a single extendedclass definition can contain no more than one inherit command. One. That's it. π«
The order of the baseExtendedclass names in the inherit list literally decides name resolution for extendedclass members. When the same member name shows up in two or more base extendedclasses, whichever base extendedclass appears first in the inherit list wins. So say extendedclasses Foo and Bar both contain the member x, and some other extendedclass 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. iykyk. π
constructor args ?init? body
Declares the args argument list and body used for the constructor, which gets invoked automatically whenever an object is created. β¨
Before the body runs, the optional init statement is used to invoke any base extendedclass constructors that require arguments. Variables in the args specification can be accessed in the init code fragment, and passed to base extendedclass constructors. Once the init statement has been evaluated, any base extendedclass constructors that haven't been executed yet get invoked automatically without arguments. This is the vibe check that ensures all base extendedclasses are fully constructed before the constructor body is executed. By default, this scheme causes constructors to be invoked in order from least- to most-specific. And that is exactly the opposite of the order that extendedclasses are reported by the info heritage command. π
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. π
destructor body
Declares the body used for the destructor, which gets invoked automatically 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. She stays. π
When an object is destroyed, all destructors in its extendedclass hierarchy are invoked in order from most- to least-specific. This is the order that the extendedclasses are reported by the info heritage command, and it is exactly the opposite of the default constructor order. π
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. π«Ά
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.
Inside the body of another extendedclass method, a method can be invoked like any other command β simply by using its name. Outside of the extendedclass 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 extendedclass that are redefined in the current extendedclass, or hidden by another base extendedclass, can be qualified using the extendedclassName::method syntax. π
proc name ?args? ?body?
Declares a proc called name. A proc is an ordinary procedure within the extendedclass 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. No object-specific stuff for procs, ngl. π
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 extendedclass 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 extendedclassName::proc. Procs in a base extendedclass that are redefined in the current extendedclass, or hidden by another base extendedclass, can also be accessed via their qualified name. β¨
variable varName ?init? ?config?
Defines an object-specific variable named varName. All object-specific variables are automatically available in extendedclass methods β they do not need to be declared with anything like the global command. Slay, no boilerplate. π
If the optional init string is specified, it's used as the initial value of the variable when a new object is created. Heads up though: 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. π
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 extendedclass definition using the configbody command. π
common varName ?init?
Declares a common variable named varName. Common variables live in the extendedclass namespace and are shared by all objects belonging to the extendedclass. They're just like global variables, except they need not be declared with the usual global command. They are automatically visible in all extendedclass methods and procs. πΈ
If the optional init string is specified, it's used as the initial value of the variable. Just like with 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 extendedclass definition. This is how you get common data members initialized as arrays. For example:
itcl::extendedclass Foo {
common boolean
set boolean(true) 1
set boolean(false) 0
}
Not me pointing out that if common data members are initialized within the constructor, they get initialized again and again whenever new objects are created. π Every. Single. Time.
public command ?arg arg ...?
protected command ?arg arg ...?
private command ?arg arg ...?
These three set the protection level for extendedclass members that get created when command is evaluated. The command is usually method, proc, variable orcommon, and the remaining arg's complete the member definition. However, 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. π
protected and private work exactly the same way β same rules, same "applies to everything command creates" energy β just swap in that protection level instead of public.
π CLASS USAGE π
Once an extendedclass has been defined, the extendedclass name can be used as a command to create new objects belonging to the extendedclass. Let's gooo. π
extendedclassName objName ?args...?
Creates a new object in extendedclass extendedclassName with the name objName. The remaining arguments get passed to the constructor of the most-specific extendedclass. That in turn passes arguments to base extendedclass 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. Cleanup crew said we're not leaving a mess. π§
If objName contains the string #auto, that string is replaced with an automatically generated name. Names have the form extendedclassName<number>, where the extendedclassName part is modified to start with a lowercase letter. In extendedclass Toaster, for example, the #auto specification would produce names like toaster0, toaster1, etc. π
And no cap β #auto can also be buried inside an object name:
fileselectiondialog .foo.bar.#auto -background red
This would generate an object named .foo.bar.fileselectiondialog0. The way it just slides in there and does its thing. β¨
π 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. She's a command now, bestie. π
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 extendedclass definition, or any of the following built-in methods.
β¨ BUILT-IN METHODS β¨
Every extendedclass object comes with a lil starter pack of methods, bestie. Here's the whole menu π
π objName cget option
Gives you access to public variables as if they were config options β it's literally mimicking the usual "cget" operation on Tk widgets, no cap. The option argument is a string shaped like "-varName", and this method hands you back the current value of the public variable varName. Slay.
π objName configure ?option? ?value option value ...?
Same vibe as cget, but for configuring β it mimics the usual "configure" operation on Tk widgets. Here's the tea:
- Call it with no arguments and it returns a list of lists describing every public variable. Each one of those lil lists has three elements: the variable name, its initial value, and its current value.
- Call it with a single option shaped like
"-varName"and it returns the info for that one variable. Just the one. Queen behavior π - Otherwise? The arguments get treated as option/value pairs assigning new values to public variables. Each variable gets its new value, and if it has any
"config"code associated with it, that code runs in the context of the extendedclass where it was defined. And if that"config"code throws an error? π« The variable gets set back to its previous value, and theconfiguremethod returns an error. No half-finished chaos here.
π objName isa extendedclassName
Returns non-zero if the given extendedclassName shows up in the object's heritage, and zero otherwise. Simple. Clean. A vibe check for ancestry πΈ
π objName info option ?args...?
Returns info about a particular object named objName, or about its extendedclass definition. The option parameter covers the following things, plus all the options the usual Tcl "info" command recognizes:
π objName info extendedclass
Returns the name of the most-specific extendedclass for object objName.
π objName info inherit
Returns the list of base extendedclasses exactly as they were defined in the "inherit" command β or an empty string if this extendedclass has no base extendedclasses. Sometimes the family tree is just... a single leaf π
π objName info heritage
Returns the current extendedclass name and the entire list of base extendedclasses, in the order they get traversed for member lookup and object destruction. This is the full ancestry scroll, top to bottom.
π objName info function ?cmdName? ?-protection? ?-type? ?-name? ?-args? ?-body?
With no arguments, this command returns a list of all extendedclass methods and procs. If cmdName is specified, it returns info for that specific method or proc. And if you don't pass any flags, this command returns a list with these elements: the protection level, the type (method/proc), the qualified name, the argument list, and the body. Flags exist so you can request just the specific elements you want from that list. Picky and efficient π
π objName info variable ?varName? ?-protection? ?-type? ?-name? ?-init? ?-value? ?-config?
With no arguments, this command returns a list of all object-specific variables and common data members. If varName is specified, it returns info for that specific data member. With no flags, this command returns a list with these elements: the protection level, the type (variable/common), the qualified name, the initial value, and the current value. Oh and β if varName is a public variable, the "config" code gets included on this list too. Flags can be used to request specific elements from this list.
π CHAINING METHODS/PROCS π
Okay so sometimes a base extendedclass has a method or proc that gets redefined with the same name down in a derived extendedclass. That's not a bug, bestie β that's the whole point. It's how the derived extendedclass handles the same operations as the base one, but with its own specialized behavior. Main character energy, inherited.
For example, say we have a Toaster extendedclass that looks like this:
itcl::extendedclass Toaster {
variable crumbs 0
method toast {nslices} {
if {$crumbs > 50} {
error "== FIRE! FIRE! =="
}
set crumbs [expr {$crumbs+4*$nslices}]
}
method clean {} {
set crumbs 0
}
}
Now we might create another extendedclass like SmartToaster that redefines the "toast" method. If we want to reach the base extendedclass method, we can qualify it with the base extendedclass name, so there's zero ambiguity:
itcl::extendedclass SmartToaster {
inherit Toaster
method toast {nslices} {
if {$crumbs > 40} {
clean
}
return [Toaster::toast $nslices]
}
}
But instead of hard-coding that base extendedclass name, we can use the "chain" command like this:
itcl::extendedclass SmartToaster {
inherit Toaster
method toast {nslices} {
if {$crumbs > 40} {
clean
}
return [chain $nslices]
}
}
The chain command searches through the extendedclass hierarchy for a slightly more generic (base extendedclass) implementation of a method or proc, and invokes it with the arguments you gave it. It starts at the current extendedclass context and searches through base extendedclasses in the order that the "info heritage" command reports them. And if another implementation just... isn't found? This command does nothing and returns the null string. π¦
π AUTO-LOADING π
Extendedclass definitions don't need to be loaded explicitly, bestie β they can be loaded as needed by the usual Tcl auto-loading facility. Each directory containing extendedclass definition files should have an accompanying "tclIndex" file. Each line in this file identifies a Tcl procedure or an [incr Tcl] extendedclass definition, plus the file where that definition can be found.
For example, suppose a directory contains the definitions for extendedclasses "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 what you use to automatically generate "tclIndex" files. Iconic, honestly.
And the auto-loader has to be made aware of this directory by appending the directory name to the "auto_path" variable. Once that's in place, extendedclasses will be auto-loaded as needed whenever they're used in an application. β¨
π§ C PROCEDURES π§
C procedures can be integrated into an [incr Tcl] extendedclass definition to implement methods, procs, and the "config" code for public variables. The rule is simple: any body that starts with "@" gets treated as the symbolic name for a C procedure.
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". That procedure can then 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 the details. Inside the procedure, extendedclass data members can be accessed like ordinary variables using Tcl_SetVar(), Tcl_GetVar(), Tcl_TraceVar(), etc. And extendedclass methods and procs can be executed like ordinary commands using Tcl_Eval(). [incr Tcl] makes all of this possible by automatically setting up the context before it runs the C procedure. Chef's kiss π€
This scheme provides a natural migration path for code development. Extendedclasses can be developed quickly using Tcl code to implement the bodies. An entire application can be built and tested. And when necessary, individual bodies can be implemented with C code to improve performance. Glow-up arc fr fr π₯
π KEYWORDS π
extendedclass, object, object-oriented
That's the whole page, bestie β we made it to the end π«Ά This one's from the itcl crew, version 4.0, and the page is dated extendedclass(3itcl). Go build something iconic with it. π
π¦ where this page comes from
- ubuntu resolute: tcl-itcl4-doc 4.3.5-1 Β· BSD-Tcl
- ubuntu stonking: tcl-itcl4-doc 4.3.8-1 Β· BSD-Tcl
- Copyright (c) 2008 Arnulf Wiedemann
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms