Hello all,
Just noticed the following behaviour in XOTcl:
Class Base Base instproc foo {} { puts "Foo in Base" } Base instproc bar {} { # Just call foo my foo } Class Sub -superclass Base Sub instproc foo {} { puts "Foo in Sub" } (Desktop) 56 % Sub a ::a (Desktop) 57 % a foo Foo in Sub (Desktop) 58 % a bar Foo in Sub
I was kind of expecting the last to say "Foo in Base", as the method call of "foo" was dispatched from the Base class level. This is an interesting problem, as I can see reasons why you might want to do the current behaviour. However, I'm worried about some of the implications of implementation details and name clashes. Suppose I implement some class Base, which as part of it's implementation has a (private) method DoStuff. Now suppose someone else sub-classes my class, and in their implementation, they also happen to have a DoStuff method - this is going to break my implementation. It seems like this is breaking encapsulation somewhat. It seems like the cases where this dynamic dispatch could be useful could also be solved by passing in an explicit callback - that way you aren't relying on an implementation detail.
Am I missing a good reason for this? My OO theory is perhaps lacking in this area. I can see that I can get around it easily by prefixing my private methods:
Base instproc BaseDoStuff {...} { ... }
but this seems a bit ugly (reminds me of pre-namespace Tcl). Does XOTcl have some other cool feature that I'm missing.
Cheers,
Neil.
On Wednesday 19 May 2004 19:30, Neil Madden wrote:
I was kind of expecting the last to say "Foo in Base", as the method call of "foo" was dispatched from the Base class level. This is an interesting problem, as I can see reasons why you might want to do the current behaviour. However, I'm worried about some of the implications of implementation details and name clashes. Suppose I implement some class Base, which as part of it's implementation has a (private) method DoStuff.
XOTcl has no private methods, every method is public. the evaluation context does not change the semantics of an invocation.
OO breaks sometimes locality, and refining existing classes is not the best concept for components.
without thinking long, i can offer two approaches. 1) The first one is rather for fun, it changes the class of the object on the fly:
Object instproc local args { set oldclass [my info class] my class [uplevel self class] set r [eval my $args] my class $oldclass return r } ... Base instproc bar {} { my local foo }
since it might have some unwanted effects, when the "local" called method (here "foo") calls other methods, which should be dispatched based on the true objects class. The help in mixins is also rather limited.
2) following your prefix approach:
Object instproc own {} { namespace tail [uplevel self class] } Object instproc private {method name arguments body} { set prefix [namespace tail [self]] [self] $method $prefix-$name $arguments $body }
one can define now:
Class Base Base private instproc foo {} { puts "Foo in Base" } ....
and call this via:
Base instproc bar {} { my [my own]-foo }
to avoid stuttering while reading, one can define a global funciton
proc own {} { namespace tail [self class] } Base instproc bar {} { my [own]-foo }
in genereal, instead of [own], [self class] could be used, but currently, the leading colons are not allowed in xotcl. i guess, we can change this.
-gustaf neumann