In the following example, the classvariable m_columns statement inside of classmethod setit creates a variable that is unusable in the ordinary way in a new namespace in the ::oo space rather than link to the class-wide variable as one would expect. This produces a bug which is hard to diagnose.
Note that if one does the same thing in the initialize section, an error is thrown: "self may only be called from inside a method". That error seems to be based on the imlementation of initialize and could probably be more helpful and direct with different wording, but at least it doesn't silently create an unreachable variable.
The workaround is to use variable instead of classvariable inside the classmethod. But this is likely to be forgotten since it doesn't seem consistent.
oo::class create test1 {
initialize {
variable m_columns [dict create initial {value1 value2 value3}]
}
classmethod setit {} {
classvariable m_columns
dict set m_columns foo {garp parp snarp}
puts [format {in setit: self=%s m_columns=%s} [self] $m_columns]
}
constructor {} {
classvariable m_columns
puts [format {in constructor: self=%s m_columns=%s} [self] $m_columns]
}
method showit {} {
classvariable m_columns
puts [format {in showit: self=%s m_columns=%s} [self] $m_columns]
}
}
% test1 setit
in setit: self=::test1 m_columns=foo {garp parp snarp}
% info object namespace ::test1
::oo::Obj106
% set r [test1 new]
in constructor: self=::oo::Obj108 m_columns=initial {value1 value2 value3}
::oo::Obj108
% $r showit
in showit: self=::oo::Obj108 m_columns=initial {value1 value2 value3}
%
% info vars ::oo::Obj106::*
::oo::Obj106::m_columns
% info vars ::oo::Obj107::*
::oo::Obj107::m_columns
% info vars ::oo::Obj108::*
%
% set ::oo::Obj106::m_columns
initial {value1 value2 value3}
% set ::oo::Obj107::m_columns
foo {garp parp snarp}
%
|