On Thu, 28 Dec 2000, Uwe Zdun wrote:
Hi,
On Tue, 26 Dec 2000 seva@design.kiev.ua wrote:
I split my application in several source files. Each of files implements one of fsm's or helper functions, and when I need to change logic of work, i simply source all files.
There are several problems with this:
- when I execute command Class Some, previous instance of this
class deleted, and all objects move to ::Object class.
this behavior is intended: from a "programming language point of view" you can not predict whether a destroyed class is going to be redefined or not. There could be another class with the same name, but with different semantics.
Ok, I agree with that point :)) (But does'nt like it too much :)) )
In cases like your application, that require a class redefinition, there are several ways to tell the language to behave like this:
- you can use the filter, as you have done to overload create.
- you can use a subclass or a mixin to change create bahavior
- or you use introspection to find out which instances are currently there and re-class these instances after sourcing to the new classes (same-named) classes
Probably a combination would work here, like a instmixin on object that checks whether a class-to-be-created exists. If yes all instances are stored in a variable. After create, the instances are re-classed back to the old class.
Or you build an instmixin tht simply does not execute the "create" on certain existing classes?
Yes, it is a solution which I use now. But probably I switch to instmixin with create overloaded.
It depends on your application case which solution is the best here ...
This problem I solve by using filter for create command on ::Object (idea
stolen from recoverypoint class :)) ). But with that second problem arrives: 2) when some instproc used as a filter, and redefined, it's filter become inactive. (so first problem arrives again, when I source recover.tcl which has recoverfilter definition) after setting filter again, all works as expected
for the same reason as we have to re-class exisiting instances, we have to set the filters to an empty list, when the method is redefined (the same is done for mixins, when the class is redefined). E.g., we can not say that in any case with "Object instproc filter" the same method is defined. But again you can easily change this behavior for certain cases with a filter or instmixin or a subclass of Object, by redefining "mixin", "instmixin", "filter", etc. so that they check whether a certain filter, mixin, or instmixin is still there. A filter on Object is probably not the best solution here, because it performs the check on every call in the system. This is a heavy performance overhead. Presumably a mixin solution is more well-suited, because it only checks for certain methods and can be used object-specifically.
In your example code a "mixin" on "Class", that just checks the Class->create method could be sufficient.
Ok, I tried another test case. Class A with two filters f1 and f2
Class A
A instproc f1 {args} { puts ">> filter f1" next }
A instproc f2 {args} { puts ">> filter f2" next }
A filter {f1 f2}
Instance of this class
A a
anything works ok: a set b 1
filter f1 filter f2
redefine f2:
A instproc f2 {args} { puts ">> new filter f2" next }
still 2 filters: A info filter f1 f2
test: a set b 1
filter f1
interesting: A info filter f1
seems like ok, but when I put it in file and execute it, I get: a set b 1
filter f1 filter f2
A filters: f1 f2 a set b 1
filter f1 filter f2
redefine f2 a set b 1
filter f1
while executing "a set b 1" (file "./a.tcl" line 35)
filter f1
Contents of file: =================================================== #!/usr/local/bin/tclsh8.2
package require XOTcl
Class A
A instproc f1 {args} { puts ">> filter f1" next }
A instproc f2 {args} { puts ">> filter f2" next }
A a A filter {f1 f2}
puts "a set b 1" a set b 1
puts "A filters: [A info filter]"
puts "a set b 1" a set b 1 puts "redefine f2"
A instproc f2 {args} { puts ">> new filter f2" next }
puts "a set b 1" a set b 1 puts "A filters: [A info filter]" puts "a set b 1" a set b 1 puts "A filters: [A info filter]"
============================================= seems that first execution of a filter after redefining leads to error