100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Tcl Object-Orientation with TclOO

How to define classes, objects, methods, and inheritance in Tcl using the built-in TclOO framework (oo::class, oo::define, oo::copy).

Advanced TclAdvanced11 min readJul 10, 2026
Analogies

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.

tcl
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]   ;# 150

Inheritance 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

Was this page helpful?

Topics covered

#Programming#TclTkStudyNotes#TclObjectOrientationWithTclOO#Tcl#Object#Orientation#TclOO#OOP#StudyNotes#SkillVeris