You are right with your observeration, all methods in xotcl are polymorphic. This is important for orthogonality, especially, when methods invocations are interceptable as with mixin classes or filters. Here is a small example, which i think demonstrates your argument. correct me, if you have something different in mind.
============ Class Base Base instproc foo {} { puts "[self class] [self proc]" my bar a b } Base instproc bar {x y} { puts "[self class] bar $x $y" }
Class Sub -superclass Base Sub instproc bar {x y} { puts "[self class] [self proc]" }
Sub b1 b1 foo ============
the invocation of "b1 foo" calls Base->foo, the invocation of "my bar a b" calls Sub->bar, your question is, how to call Base->bar instead (like for c++ non-polymorphic methods)
As you pointed out, there are many ways to tweak the behavior. The important point is, how should/could some kind of non-polymorphic call lead to some "defensible semantics", esp. how should it behave it should behave in cases of e.g. next, or with the presence of interceptors.
The most rude apporach is to use tcl-functions instead of methods and bypass this way the xotcl dispatcher. Since every xotcl method is a tcl proc, this is doable with some little magic:
============== proc myown {proc args} {uplevel ::xotcl::classes[self class]::$proc $args} ... Base instproc foo {} { puts "[self class] [self proc]" myown bar 1 2 } ... ==============
Here, myown calls Base->bar, not Sub->bar. This is the archetype of a monoporphic call.
The downside is that the invocation of the method happens in the same xotcl frame. You might or might not be concerned about this. "logically", "bar" is invoked in Base->foo, and does not leave the callframe. Queries and calls based on the xotcl stack will reflect this, a [self proc] in bar will still return "foo", a next will call shadowed methods of "foo". By bypassing the xotcl dispatcher, filters and mixins will not be able to intercept the invocation of "Base->foo".
Another approach, as you indicated is to alter the relation between the class and the object temporarily.
============== proc as_my_instance args { set __oldclass [my info class] my class [uplevel self class] set r [uplevel my $args] my class $__oldclass set r } .... Base instproc foo {} { puts "[self class] [self proc]" as_my_instance bar 1 2 } ... ==============
while this is something which looks strange to somebody with a c++ background, this is not so far fetched, if one keeps in mind that the relation between an object and a class is just an association (like a pointer in c). The semantics are less wierd than these of the first approach: The invocation of "as_my_instance" means that everything dispatched behaves as if the object would be an instance of the current class. This will work nicely all other constructs like "next", etc. One should actually put a catch around the invocaton of the method....
Finally, the question should be adressed, whether or not the non-polymorphic call is needed. Who should call "bar" aside from "foo"? If this is something special to this class, why not model this as a proc of Base:
============== Class Base Base instproc foo {} { puts "[self class] [self proc]" [self class] bar 1 2 } Base proc bar {x y} { puts "[self ] [self proc] $x $y" }
Class Sub -superclass Base Sub proc bar {x y} { puts "[self class] [self proc]" }
Sub b1 b1 foo ============== If the behavior of "bar" needs inheritance etc, meta-classes or mixinclasses can be used. Again, there is no strange intererence with other xotcl mechanisms.
all the best -gustaf neumann