For Programmers: Free Programming Magazines  


Home > Archive > Tcl > July 2004 > XOTcl question: How to invoke method in parent class ?









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author XOTcl question: How to invoke method in parent class ?
Helmut Giese

2004-07-22, 8:57 pm

Hello out there,
normally, invoking a method from a parent class is easy: just use
'next', thus invoking the parent's method with the _same name_.

However, I'm in a different context: Within a method 'foo' of a
derived class I need to call method 'bar' of the _parent_ class - not
the derived method 'bar'. Something like this:

Derived instproc foo {args} {
call parent's method 'bar'
}

I don't arrive at figuring out the correct syntax. Any help will be
greatly appreciated.
Helmut Giese
Gustaf Neumann

2004-07-23, 8:57 am

hgiese@ratiosoft.com (Helmut Giese) wrote in message news:<41002908.1726898@News.Individual.DE>...
> Hello out there,
> normally, invoking a method from a parent class is easy: just use
> 'next', thus invoking the parent's method with the _same name_.
>
> However, I'm in a different context: Within a method 'foo' of a
> derived class I need to call method 'bar' of the _parent_ class - not
> the derived method 'bar'. Something like this:
>
> Derived instproc foo {args} {
> call parent's method 'bar'
> }
>
> I don't arrive at figuring out the correct syntax. Any help will be
> greatly appreciated.
> Helmut Giese


concering terminology: xotcl uses "parent" in context with
aggregation (nesting of objects, classes). The simple answer
to your questing is below.

Class Bar
Bar instproc bar args {puts "i am [self proc] in [self class]"}
Class Derived -superclass Bar
Derived instproc foo {args} {
puts "i am [self proc] in [self class]"
my bar ...
}

Derived d1
d1 foo

but maybe, you have as well a method bar defined in Derived, but you
want to skip it. there are ways to do this, but i would not go into
that.... what are you trying to achive?

-gustaf
Helmut Giese

2004-07-23, 8:57 am

On 23 Jul 2004 01:58:16 -0700, neumann@wu-wien.ac.at (Gustaf Neumann)
wrote:
Hello Gustaf,
thanks for your response.
[snip]
> concering terminology: xotcl uses "parent" in context with
> aggregation (nesting of objects, classes).

Sorry for the confusion - what I meant was base class.

> what are you trying to achive?

Well, since you ask :) here is the whole story
-----
if 0 { I have objects which can form sort of a "process chain": if the
variable 'output' is not empty, then (after doing their own
processing) they invoke output's method. In this design the objects
are not aware _who_ called them: It might be the "user" or it might be
some object which had already performed some operation on the data.}

package require XOTcl
namespace import -force xotcl::*

Class Base -parameter {{output ""}}
Base instproc foo args {
my instvar output
puts "([self]) i am [self proc] in [self class]"
if { $output != "" } {
# got a successor: call it
$output foo $args
}
}

# base1 is a simple processor
Base baseA
# baseB has a "successor" to call
Base baseB -output baseA
baseB foo abc

if 0 {Now the need for a special object arose: One that has a
preprocessor of its own to which it passes the data before acting
itself on it. Additional design aspect: this object "knows" of a
preprocessor, but the outside world doesn't.}

Class Derived -superclass Base -parameter {prepro}
Derived instproc init {args} {
# create preprocessor and link it back to me
my set prepro [Base prepro -output [self]]
}

Derived instproc foo {args} {
puts "([self]) i am [self proc] in [self class]"
# forward call to preprocessor
# [my set prepro] foo $args
# this doesn't work: we will run into infinite recursion
}

Derived d
d foo

if 0 {The above solution doesn't work, because Derived's foo will call
its preprocessor's foo, which call back to Derived's foo, etc. The
next idea was to provide an additional variable (fctName) which
defaults to 'foo' but which can be changed.}

Class Base2 -parameter {{output ""} {fctName foo}}
Base2 instproc foo args {
my instvar output fctName
puts "([self]) i am [self proc] in [self class]"
if { $output != "" } {
# got a successor: call it with whatever function was provided
$output $fctName $args
}
}

puts "\nSecond attempt"
Base2 base2A
Base2 base2B -output base2A
base2B foo abc

if 0 {Now I try to break the recursion by introducing a worker
function 'doFoo' which can safely be called from the preprocessor.}

Class Derived2 -superclass Base -parameter {prepro}
Derived2 instproc init {args} {
# create preprocessor and link it back to the new function
my set prepro [Base2 prepro -output [self] -fctName doFoo]
}

Derived2 instproc foo {args} {
puts "([self]) i am [self proc] in [self class]"
# forward call to preprocessor: no recursion
[my set prepro] foo $args
}

Derived2 instproc doFoo {args} {
puts "([self]) i am [self proc] in [self class]"
puts " and I need to call Base2's foo with my args to get the
work done"
}

Derived2 d2
d2 foo
----
Does this make sense? I am rather certain that my problem can easily
be solved but I just cannot figure out the correct syntax.
Thanks for any thoughts on this.
Best regards
Helmut Giese

Gustaf Neumann

2004-07-23, 8:56 pm

hgiese@ratiosoft.com (Helmut Giese) wrote in message news:<4100ea43.7445372@News.Individual.DE>...
> Well, since you ask :) here is the whole story
> -----
> if 0 {Now the need for a special object arose: One that has a
> preprocessor of its own to which it passes the data before acting
> itself on it. Additional design aspect: this object "knows" of a
> preprocessor, but the outside world doesn't.}


Helmut, here is a rather simple version of what i think you
are looking for.

####################################
Class Base -parameter {{output {}}}
Base instproc foo {args} {
puts "[self] i am [self proc] in [self class]"
foreach d [my output] {eval $d foo $args}
}

Base baseA
Base baseB -output baseA

Base prepro
Class Derived -superclass Base
Derived instproc init {} {
my set output [linsert [my set output] 0 prepro]
}
Derived d -output baseA
d foo
####################################

you get as output
::d i am foo in ::Base
::prepro i am foo in ::Base
::baseA i am foo in ::Base

note that prepro is called before the other
delegations, but not before the methods of Derived
(since delegation happens in the Base class).

If you are happy with this, don't read on.
There is a more flexible approach based on
delegation to a mixin class, which is not
for beginners. The nice part is that you
can refine the classes with mixins over
various levels.

Since only classes can be used for
mixin into objects, we define Base as
a meta-class, such that instances (such as the
preprocessor) are classes which can be mixed in.
If you play with this, i would
recommend to redefine the unknown method
of Class and create objects and classes
explicitely with the create method. Otherwise
the call to unknown methods results in new objects....

-gustaf

########################################
#
Class Base -parameter output -superclass Class
Base instproc init {} {
my instproc foo args {eval [self class] foo $args; next}
}
Base instproc foo args {
my instvar output
puts "[self] i am [self proc] in [self class]"
if {[my exists output]} {# got a successor: call it
$output foo $args
}
}

Base baseA
Base baseB -output baseA
baseB foo abc

Base prepro
prepro instproc foo {} { puts "[self] i am [self proc] in [self class]"; next}

Base d -mixin prepro -output baseB
d foo
########################################
#
Helmut Giese

2004-07-28, 9:08 pm

Hello Gustaf,
thank you very much for your explanation(s).

[snip 1st example]
>If you are happy with this, don't read on.
>There is a more flexible approach based on
>delegation to a mixin class, which is not
>for beginners. The nice part is that you
>can refine the classes with mixins over
>various levels.

Of course I read on ...
I studied your second example, because I'd like to get more "feeling"
for what can be accomplished using mixins. It's a very powerful
concept, but (having learned OOP with C++) it's still a bit foreign
for me.
For the problem at hand, however, it did not provide a solution, but I
still profited from it because I learned a bit more. I found a
different route to solve it though, so all is well. In case you're
interested I'll describe it below.

Background: I try to model binary (hardware) counters
- they count up as far as their number of bits allow
- then wrap around and restart at zero,
- at which point they might cause a hardware interrupt or
- provide _one_ pulse for another counter to count (in which case they
are commonly called 'prescaler').
---
package require XOTcl
namespace import -force xotcl::*

Class Counter -parameter {{output ""} {fctName count}}
# We provide _two_ access functions: one which does the actual work
('doCount')
# and one which just calls the other ('count')
Counter instproc doCount cnt {
my instvar output fctName
puts "([self]) i am [self proc] in [self class] with cnt = $cnt"
if { $output != "" } {
# got a successor: call it
$output $fctName [expr {$cnt / 2}]
}
}
# forward call
Counter instproc count cnt {[self] doCount $cnt}

########## let's use them #########
Counter cnt1
Counter cnt2 -output cnt1
cnt2 count 100

if 0 {Now I needed a Counter with an integrated prescaler - without
wanting to publish all the interface details. User should be able to
handle this "Extended Counter" just like an ordinary Counter.}

Class ExtCounter -superclass Counter
ExtCounter instproc init {args} {
# create prescaler and connect it back to own counting function
my instvar prescaler
set prescaler [Counter prescaler -output [self] -fctName doCount]
}
ExtCounter instproc count cnt {
puts "([self]) i am [self proc] in [self class] with cnt = $cnt"
# forward call to prescaler
[my set prescaler] count $cnt
}

puts "\nCounter with integrated prescaler"
ExtCounter xcnt
xcnt count 100

puts "Counter with integrated prescaler and an additional postscaler"
Counter postscaler
ExtCounter xcnt2 -output postscaler
xcnt2 count 100
---
Ok, from a desing POW it has a bit of a hack, but it is still a simple
design and above all it works.

Gustaf, I want to thank you again for XOTcl - I consider it a very
valuable addition for my toolbox.
Best regards
Helmut Giese
Gustaf Neumann

2004-07-28, 9:08 pm

Helmut, maybe you find the following example useful, where
pre- and postscalers can be configured/reconfigured
dynamically via mixins:

Greetings
-gustaf

Class Counter
Counter instproc count cnt {
puts "([self]) i am [self proc] in [self class] with cnt = $cnt"
return $cnt
}

Class PreScaler -superclass Counter
PreScaler instproc count cnt {
puts "([self]) i am [self proc] in [self class] with cnt = $cnt"
next [expr {$cnt / 2}]
}
Class PostScaler -superclass Counter
PostScaler instproc count cnt {
set cnt [expr {[next] / 2}]
puts "([self]) i am [self proc] in [self class] with cnt = $cnt"
}
puts ======
Counter c1
c1 count 100
puts ======
c1 mixin PreScaler
c1 count 100
puts ======
c1 mixin {PreScaler PostScaler}
c1 count 100
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com