** Variables in TclOO **
*** Variable Commands ***
With TclOO, there are nowat least three (cormmands four!)in Tcl 8.5+ named [variable] commands. They are:
* `'''::[variable]''' ''name''`
* `'''::[variable]''' ''?name value?'' ''?...?''`
Makes a namespace variable visible in the current scope.
* `'''::[oo::define]''' ''$class'' '''variable''' ''?-slotOperation?'' ''?name ...?''`
Makes an instance variable visible in all methods defined in the current class.
* `'''::[oo::objdefine]''' ''$object'' '''variable''' ''?-slotOperation?'' ''?name ...?''`
Makes an instance variable visible in all methods defined on the object.
This can be thought of as a special case of `::oo::define::variable`.
* `'''[my] variable''' ''?name ...?''`
* `'''::[oo::object] variable''' ''?name ...?''`
Makes an instance variable visible in the current scope. This is an unexported method of `::oo::object`, and equivalent to the following definition:
======
oo::define oo::object method variable {args} {
foreach var $args {
uplevel 1 [
list namespace upvar [namespace current] $var $var
]
}
}
oo::define oo::object unexport variable
======
Another utility method on `oo::object` is (almost-)equivalently defined as:
======
oo::define oo::object method varname {name} {
return [namespace current]::$name
}
======
*** Where are my variables? ***
Instance variables are just namespace variables in the object's namespace. So, inside a method:
======
my variable foo
variable foo
======
both have the same effect. They differ importantly in how ''multiple arguments'' are treated, so be careful. One might prefer to use `my variable` in methods, as it more closely resembles `oo::define variable`.
`oo::define` and `oo::objdefine` arrange that the variable is ''automatically'' made visible in all methods defined ''at the same level''.
This is similar to having `variable ''name''` implicitly prepended to the methods' bodies.
"At the same level" means simply that object variables are made visible in object methods (both defined with `[oo::objdefine]`), and class variables are made visible in methods on the same class (ie: not superclasses, subclasses or mixins).
**** Choose Good Names ****
When using inheritance or mixins, it's important to be aware that while `::[oo::define] variable`
only makes a variable ''visible'' to methods in the current class, the variable will ''exist'' in
the object's namespace. Thus collisions are possible, so beware:
======
oo::class create S {
variable x
method sx {} {
set x 0
}
}
oo::class create M {
variable x
method mx {} {
incr x 3
}
}
oo::class create C {
superclass S
mixin M
variable x
method cx {} {
incr x 5
}
}
C create t
puts [list [t sx] [t cx] [t mx] [t sx] [t cx] [t mx]]
# => 0 5 8 0 5 8
======
This sort of collision might be harmful if the author of `C` is unaware that `M` uses the name `x` for its own purposes.
Thus, if you're publishing a class to use as a superclass or a mixin, the variables it uses should be considered part of the specification.
For "private" data, short and likely-to-collide names should be avoided.
It might be a good idea to contain it in a uniquely-named array or sub-object. Or perhaps a dict, or a coroutine!
[RZ] or have a look on [TclOO private variables]
** See Also **
* [Inspecting TclOO]
* [TclOO]
* http://www.magicsplat.com/articles/oo.html%|%APN's excellent TclOO Article%|% which calls these "data members"
<<categories>>TclOO