- It just works. Kudos to Donal
- - Will Duquette,Twentieth Annual Tcl/Tk Conference (2013)
Development edit
Commands edit
- ::oo::class
- new in 8.6
- ::oo::copy
- new in 8.6
- ::oo::define
- new in 8.6
- ::oo::objdefine
- ::oo::object
- info
- info class
- provides introspection of classes (many subcommands)
- info object
- provides introspection of objects (many subcommands)
Method Commands edit
The following commands are only available within the body of a methodDescription edit
DKF (mostly):TclOO is a core for other OO extensions, but in order to do that job properly it also needs to be a basic OO framework itself. The other thing that it isn't is a class library. That can go in tcllib just nicely.OO support in the core distribution can be completely ignored except when it is providing a specific benefit to a script. At an implementation level, the benefit is that it scopes the development and keeps the amount of work required sane and the delivery schedule practical. You might or might not think of this as a benefit... :-)TclOO borrows many concepts from XOTcl, so there's definite continuity from Smalltalk in there. Not everything though; incr Tcl was an influence too and that's got C++ genes.Developers may choose to use ::tcl::oo directly to do their work, or they may choose to use other object systems, e.g., snit, incr tcl, XOTcl, which themselves use TclOO and then provide additional functionality/flavour.In terms of rewriting things to use TclOO, some classes probably will be rewritten, e.g. quite possibly code to support chan create better, maybe a megawidget framework, and TDBC of course) but there won't be a vast number. The whole world needn't be changed. Tcl was working fairly well beforehand.News edit
TclOO 1.0.1 was released on 2013-09-26. It corresponds to the version included as part of Tcl 8.6.1. Download.TclOO 1.0 was released on 2012-12-21. It corresponds to the version included as part of Tcl 8.6.0. Download.TclOO 0.6 has been released on 2008-10-14. It corresponds to the version included as part of Tcl 8.6a3.Original announcement on news:comp.lang.tcl on 01-Oct-2007 (note links are outdated now):I'm very pleased to announce that TclOO version 0.1 is now released. It's hosted in the Tcl project at [SourceForge], so you can download the source package from: http://sf.net/project/showfiles.php?group_id=10894&package_id=247402 It requires Tcl 8.5b1 to build and operate; see the enclosed `README.txt` for details on how to build this TEA-based package. No promises on whether I'll do a binary package for any platforms as yet. :-) Details about this package can be found in the Wiki, naturally, at http://wiki.tcl.tk/TclOO and any problems should be reported using Tcl's issue trackers at http://sf.net/tracker/?group_id=10894&atid=110894 with the summary field prefixed by "TclOO:".
Examples edit
- Playing with TclOO
- TclOO Tricks
- TclOO Channels
- coroutine
- contains a TclOO example by CMcC
Basic Example edit
package require TclOO; #if loading for the first time; not required on Tcl 8.6 oo::class create summation { constructor {} { variable v 0 } method add x { variable v incr v $x } method value {} { variable v return $v } destructor { variable v puts "Ended with value $v" } } set sum [summation new] puts "Start with [$sum value]" for {set i 1} {$i <= 10} {incr i} { puts "Add $i to get [$sum add $i]" } $sum destroy ;# only destroy the $sum object. 'summation destroy' destroys ALL summation objects --Duoaswhich gives:
Start with 0 Add 1 to get 1 Add 2 to get 3 Add 3 to get 6 Add 4 to get 10 Add 5 to get 15 Add 6 to get 21 Add 7 to get 28 Add 8 to get 36 Add 9 to get 45 Add 10 to get 55 Ended with value 55
Should you see the error message
attempt to provide package TclOO 0.1.1 failed: package TclOO 0.1 provided insteadDuoas If I should see that message, then what?DKF: Then stop using that old version! I really don't recommend using less than 1.0 nowadays…
TclOO::ext edit
I collected some TclOO extension in a package here: https://github.com/arthurschreiber/tcloo-extCurrently included is a Reference Counting system inspired by ObjectiveC/Cocoa to make memory management easier and a class method inheritance through MetaClasses (not using mixins).Discussion edit
APN I don't quite follow the discussion below about automatically bringing variables into scope. Isn't that what the variable inside a class definition does?
class create C { variable a b }would have variables a and b automatically brought into scope in all methods. Perhaps the discussion originated before variable was implemented. If someone can confirm this, please delete this and the discussion below because it is misleading.
- DKF: Indeed, that's what the variable declaration does. Now. It didn't when the discussion was held. It also doesn't bring in all variables because that turns out to be more problematic when mixed with inheritance.
my variable {*}[info vars [namespace current]::*]IOW, set up methods to automatically have access to all object state as plain variables (as in Itcl). The above line would be added in front of all method definitions, using a small wrapper (am generating methods dynamically anyway).This assumes that all variables are defined in the constructor.escargo Does this use of variable contrast confusingly with the Tcl variable where something like that would assign the names of half the variables as the values of the other half of the variables?jcw - Well, I'm just trying it out, so don't shoot me ;) - although so far I tend prefer this over the "variable" cmd.escargo - I was just asking a question. It's just that having my variable work not like variable might be considered confusing.jcw - Here's an example with some output which may help those who don't have TclOO yet:
oo::class create dog { method a {} { puts a1-[namespace current] puts a2-[namespace path] foreach x [namespace path] { puts a3-$x-[info commands ${x}::*] } puts a4-[info vars [namespace current]::*] my variable e set e f puts a5-[info vars [namespace current]::*] } self method b {} { puts b1-[namespace current] puts b2-[namespace path] foreach x [namespace path] { puts b3-$x-[info commands ${x}::*] } puts b4-[info vars [namespace current]::*] my variable e set e f puts b5-[info vars [namespace current]::*] } } dog create fifi fifi a dog b # Output: # a1-::oo::Obj4 # a2-::oo::Helpers # a3-::oo::Helpers-::oo::Helpers::self ::oo::Helpers::next # a4- # a5-::oo::Obj4::e # b1-::oo::Obj3 # b2-::oo::Helpers ::oo # b3-::oo::Helpers-::oo::Helpers::self ::oo::Helpers::next # b3-::oo-::oo::InfoClass ::oo::class ::oo::InfoObject ::oo::object \ # ::oo::copy ::oo::define # b4- # b5-::oo::Obj3::e
- MHo 2015-02-24 This doesn't work for me. There's no command 'dog b'. Should it be 'self method b…' instead of 'self.method b…' ? Would be fine if there where a 'TclOO for OO-Dummies' somewhere....
- DKF: Yes, it should. The self.blah syntax was an interim thing that got removed once I had the more general self syntax.
Aspects with TclOO edit
DKF: The following example is ripped from the documentation of next:oo::class create cache { filter Memoize method Memoize args { # Do not filter the core method implementations if {[lindex [self target] 0] eq "::oo::object"} { return [next {*}$args] } # Check if the value is already in the cache my variable ValueCache set key [self target],$args if {[info exist ValueCache($key)]} { return $ValueCache($key) } # Compute value, insert into cache, and return it return [set ValueCache($key) [next {*}$args]] } method flushCache {} { my variable ValueCache unset ValueCache # Skip the cacheing return -level 2 "" } } oo::object create demo oo::objdefine demo { mixin cache method compute {a b c} { after 3000 ;# Simulate deep thought return [expr {$a + $b * $c}] } method compute2 {a b c} { after 3000 ;# Simulate deep thought return [expr {$a * $b + $c}] } }
puts [demo compute 1 2 3] ? prints "7" after delay puts [demo compute2 4 5 6] ? prints "26" after delay puts [demo compute 1 2 3] ? prints "7" instantly puts [demo compute2 4 5 6] ? prints "26" instantly puts [demo compute 4 5 6] ? prints "34" after delay puts [demo compute 4 5 6] ? prints "34" instantly puts [demo compute 1 2 3] ? prints "7" instantly demo flushCache puts [demo compute 1 2 3] ? prints "7" after delayjcw: ''Way cool, great separation of functionality. Next step: a Metakit backed cache? ;)DKF: I've thought more about this, and have written an Aspect Support Class for TclOO.
APW 2007-06-06: For discussion of Itcl related topics for a new implementation based on this TIP see tclOO missing features for Itcl
Performance Measurement edit
DKF 2007-09-20: As seen in my Tck2k7 paper, TclOO is really quite fast. Here's those performance figures (correct with 8.5b1 on my ancient laptop).OO System | Objects Made (s?¹) | Method Calls (s?¹) |
---|---|---|
TclOO 0.1 | 32800 | 206000 |
itcl 3.4.0 | 22500 | 128000 |
XOTcl 1.5.5 | 18500 | 87500 |
Snit 2.1 | 2080 | 54700 |
Snit 1.2 | 1020 | 24700 |
stooop 4.4.1 | 13900 | 26700 |
OO System | Objects Made (s?¹) | Method Calls (s?¹) |
---|---|---|
TclOO 0.3 | 121000 | 981000 |
itcl 3.4.0 | 87900 | 573000 |
XOTcl 1.6.0 | 87200 | 404000 |
Snit 2.2.1 | 7190 | 881000 |
The script used to create the performance data is below. (Well, I actually did it interactively over a few runs, so I don't warrant that this script will really work...)
Performance Analysis Script
package require Tcl 8.5b1 # Compute Calls Per Second of a script # Note that this script is self-tuning; it prefers to execute a script for around a second
proc cps {script} { # Eat the script compilation costs uplevel 1 [list time $script] # Have a guess at how many iterations to run for around a second set s [uplevel 1 [list time $script 5]] set iters [expr {round(1/([lindex $s 0]/1e6))}] if {$iters < 50} { puts "WARNING: number of iterations low" } # The main timing run set s [uplevel 1 [list time $script $iters]] set cps [expr {round(1/([lindex $s 0]/1e6))}] puts "$cps calls per second of: $script" }
#-------------------------------------------------------------------------- puts "using Itcl..." package require Itcl 3.4 namespace path itcl
class foo { variable x constructor {} { set x 1 } method bar {} { set x [expr {!$x}] } } foo f cps {f bar} delete object f cps {delete object [foo f]} delete class foo
#-------------------------------------------------------------------------- puts "using XOTcl..." package require XOTcl 1.5.5 namespace path xotcl
Class create Foo Foo parameter x Foo instproc init {} { my set x 1 } Foo instproc bar {} { my instvar x set x [expr {!$x}] } Foo create f cps {f bar} f destroy cps {[Foo create f] destroy} Foo destroy
#-------------------------------------------------------------------------- puts "using TclOO..." package require TclOO 0.1 namespace path oo
class create foo { constructor {} { variable x 1 } method bar {} { variable x set x [expr {!$x}] } } foo create f cps {f bar} f destroy cps {[foo create f] destroy} foo destroy
#-------------------------------------------------------------------------- puts "using snit..." package require snit 2.1
snit::type foo { variable x constructor {} { set x 1 } method foo {} { set x [expr {!$x}] } } foo f cps {f bar} f destroy cps {[foo f] destroy} foo destroy
#-------------------------------------------------------------------------- puts "using stooop..." # Must go last because it plays games with proc which might disturb the # performance of other OO systems. Note that stooop has both virtual and # non-virtual methods, with very different performance profiles. The virtual # ones are much more comparable in capability to other OO systems... package require stooop 4.4.1 namespace path stooop
class foo { proc foo {this} { set ($this,x) 1 } proc ~foo {this} {} virtual proc bar {this} { set ($this,x) [expr {!$($this,x)}] } proc bar-nv {this} { set ($this,x) [expr {!$($this,x)}] } } set f [new foo] cps {$f bar} cps {$f bar-nv} delete $f cps {delete [new foo]}
See Also edit
- TIP #257: Object Orientation for Tcl
- Megawidgets with TclOO
- TclOO and configure
- Work in progress for a configuration system to go with above megawidgets stuff
- Abstract base classes with TclOO
- Fun with TclOO, coroutines and apply
- TclOO Method Dispatch
- Serializing TclOO objects
- typedlist
- TclOO trace filter
- MeTOO
- emulates TclOO for Tcl 8.4
- TclOO Tutorial
- JBR's tcloo.tcl
- Self on a class-based OO system
- Illustrates the trick of mixing a class into itself so that it can serve as a prototype in a prototype-oriented objected system. The TclOO variant of ycl shelf will also use this mechanism.
- TclOO widget/object framework, by RZ
- adds some features to vanilla TclOO, including private variables, some enhancements to constructor and destructor, new class methods like option ... and component ...
- TclOO Introductory Article
- Please redirect any comments or corrections to the BOOK Tcl Programming for Windows page.