Object-Oriented Programming with TclOO
TclOO, built into the core since Tcl 8.6, provides classes, single and multiple inheritance, method dispatch, and mixins without requiring an external OO extension. oo::class create Account defines a class, oo::define Account { method deposit {amt} { ... } } attaches methods to it, and Account new or Account create accountName instantiates an object - new returns an autogenerated object name like ::oo::Obj23, while create lets you choose the object's name explicitly, which matters when you want a predictable, referenceable handle rather than an opaque generated one.
Cricket analogy: Choosing Account create checkingAccount over Account new is like a franchise naming a player 'Player7' on the roster sheet instead of letting the league auto-assign an anonymous squad number nobody can easily reference.
Defining Methods, Constructors, and State
Every TclOO object carries its own private variable storage, distinct from any other instance of the same class; inside a method body, my variable balance links that method to the calling object's own copy of balance rather than a shared or global one. constructor {startingBalance} { my variable balance; set balance $startingBalance } runs automatically when an object is created, and destructor { ... } runs automatically when an object is destroyed (via my destroy or the class going out of scope), making it the natural place to release any resources - like an open channel - the object acquired during its lifetime.
Cricket analogy: Each object having its own private variable storage is like every player on a squad keeping an individual fitness log - two players both tracking 'sprint_time' never see or overwrite each other's numbers.
oo::class create Account {
variable balance owner
constructor {ownerName startingBalance} {
set owner $ownerName
set balance $startingBalance
}
method deposit {amt} {
incr balance $amt
return $balance
}
method withdraw {amt} {
if {$amt > $balance} {
error "insufficient funds" {} {ACCOUNT OVERDRAWN}
}
incr balance -$amt
return $balance
}
method balance {} { return $balance }
}
Account create checking alice 100
checking deposit 50
puts [checking balance] ;# 150Inheritance and Mixins
oo::class create SavingsAccount { superclass Account; method addInterest {rate} { my variable balance; incr balance [expr {int($balance * $rate)}] } } inherits every method and variable declaration from Account, and TclOO supports multiple inheritance by listing more than one class after superclass, resolved through a C3 linearization order much like Python's MRO. next passes control up the inheritance chain from within an overriding method, so method deposit {amt} { puts "logging deposit"; next $amt } can add behavior before delegating to the parent class's original implementation rather than replacing it outright. oo::define Account { mixin Loggable } achieves a lighter-weight form of composition, layering in a class's methods without a full superclass relationship.
Cricket analogy: SavingsAccount inheriting from Account is like an all-rounder inheriting a batting technique from a specialist batting coach's program while adding their own bowling-specific training on top.
'self' inside a method (accessed via [self]) refers to the current object's own name, and [self class] returns the class the object was instantiated from - useful for generic logging methods that need to report which specific instance and class triggered them without hardcoding either.
Declaring 'variable balance' at the class body level (as in the Account example) only declares the variable's name for every instance - it does not initialize it. Reading $balance in a method before the constructor has set it will raise an undefined-variable error, so constructors must always explicitly initialize every declared instance variable.
- oo::class create defines a class; oo::define attaches methods, constructors, and variable declarations to it.
- Account new auto-generates an object name; Account create name lets you choose an explicit, referenceable name.
- Each object has its own private variable storage, accessed inside methods via 'my variable varname'.
- constructor runs automatically on object creation; destructor runs automatically on object destruction.
- superclass declares inheritance, with 'next' delegating control up the chain from an overriding method.
- TclOO supports multiple inheritance, resolved via C3 linearization, and lighter-weight composition via mixin.
- Class-level variable declarations only name a variable; constructors must explicitly initialize its value.
Practice what you learned
1. What is the key difference between 'Account new' and 'Account create checking'?
2. How does a method access an object's own instance variable in TclOO?
3. What does calling 'next' inside an overriding method do?
4. When does a TclOO destructor run?
5. What is the risk of declaring 'variable balance' at the class body level without setting it in the constructor?
Was this page helpful?
You May Also Like
Namespaces in Tcl
How Tcl's namespace command organizes procedures and variables into separate scopes to avoid naming collisions in larger programs.
Error Handling with catch and try
How Tcl scripts detect, inspect, and recover from runtime errors using the catch command and the more structured try/on/finally syntax.
File I/O in Tcl
Reading, writing, and managing files and channels in Tcl using open, read, gets, puts, and the channel configuration commands.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics