[Xotcl] "Simple Delegation" revisited (long post)
Sheik Yussuff
sheik@carib-link.net
Sun, 8 Jul 2001 14:10:09 -0300
This is a multi-part message in MIME format.
------=_NextPart_000_000B_01C107B7.B25AF6C0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Just over 6 months ago,Catherine Letondal raised
the issue of implementing "simple delegation".
Professor G. Neumann replied with some code showing
how it can be done as well as suggesting that one may
use a filter to filter all methods or an instmixin
to target specific methods for delegation.
I am now learning Tcl and XOTcl (a week or so now)at the
same time and have decided to try the filter approach.
The Experiment:
1. Create a meta-class SimpleDelegation
2. add a filter sdFilter to this meta-class
3. add an instproc setDelegate
4. Create classes A and B using SimpleDelegate
5. Create class C using Class
6. A has as delegate(instvar) an object of class B;
B has as delegate an object of class C
7. A,B and C has a method "m" defined
The Problem: (Using Windows binary ver 0.85)
I extended Prof. Neumann's code to handle above
and it works.(see Code1 below)
My experiment(Code 2) works only for the following
cases(that I tested):
1. A,B and C has a method "m".
2. The instvar delegate removed from B
It does not work when I rename the method
"m" in class C to "m2".
In this case I expect an object of class B to
execute "m" but instead I get an object of class
A executing "m" instead.
I would be grateful for any pointers to resolve
this problem.
Also I want to try to implement delegation as
described by Prof. Lieberman(OOPSLA 1986 paper).
Will be grateful for any pointers on this also.
...............
Code1: Prof Neumann's code inelegantly extended
Class A -parameter delegate
A instproc handleDelegation {result} {
if {[[self] exists delegate]} {
set context [::info level -1]
#look for method in delegated object
if {[[[self] set delegate] procsearch [lindex $context 0]] !=3D "" } {
::upvar $result y
set y [eval [[self] set delegate] $context]
return 1
}
}
return 0
}
A instproc m {x} {
if {[[self] handleDelegation r]} {
return $r
} else {
puts "[self] [self class] [self proc] $x";
return [next]
}
}
Class B -parameter delegate
B instproc handleDelegation {result} {
if {[[self] exists delegate]} {
set context [::info level -1]
#look for method in delegated object
if {[[[self] set delegate] procsearch [lindex $context 0]] !=3D "" } {
::upvar $result y
set y [eval [[self] set delegate] $context]
return 1
}
}
return 0
}
B instproc m {x} {
if {[[self] handleDelegation r]} {
return $r
} else {
puts "[self] [self class] [self proc] $x";
return [next]
}
}
Class D
D instproc m2 {x} {
puts "[self] [self class] [self proc] $x"
next
return [expr {$x*2 + [[self] set v]}]
}
D d1
d1 set v 100
B b1 -delegate d1
A a1 -delegate b1
puts "result =3D [a1 m 123]"
...............................................
Code2: My Try using filters
#create SimpleDelegation as a meta-class
Class SimpleDelegation -superclass Class
SimpleDelegation instproc sdFilter args {
set method [self calledproc]
if {[[self] exists delegate]} {
set del [[self] set delegate]
#if delegate has method then dispatch it.
if {[$del procsearch $method] !=3D ""} {
return [eval [$del $method $args]]
}=20
return [next];
}
}
SimpleDelegation instproc init args {
[self] filterappend [self class]::sdFilter
next
[self] instproc setDelegate {d} {
[self] set delegate $d
}
}
SimpleDelegation A -parameter delegate
SimpleDelegation B -parameter delegate
A instproc m {x} {
puts "[self] [self class] [self proc] $x"
return [next]
}
B instproc m {x} {
puts "[self] [self class] [self proc] $x"
next
return [expr {$x*2 + [[self] set v]}]
}
Class C
#method "m" renamed to "m2" here.
C instproc m2 {x} {
puts "[self] [self class] [self proc] $x"
next
return [expr {$x*3 + [[self] set v]}]
}
A a
B b
a setDelegate b
b set v 100
C c
b setDelegate c
c set v 100
puts "result =3D [a m 123]"
..................................................
Regards,
Sheik Yussuff
email: sheik@carib-link.net
------=_NextPart_000_000B_01C107B7.B25AF6C0
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META content=3D"text/html; charset=3Diso-8859-1" =
http-equiv=3DContent-Type>
<META content=3D"MSHTML 5.00.2614.3500" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV><FONT size=3D2>
<P>Just over 6 months ago,Catherine Letondal raised</P>
<P>the issue of implementing "simple delegation".</P>
<P>Professor G. Neumann replied with some code showing</P>
<P>how it can be done as well as suggesting that one may</P>
<P>use a filter to filter all methods or an instmixin</P>
<P>to target specific methods for delegation.</P>
<P>I am now learning Tcl and XOTcl (a week or so now)at the</P>
<P>same time and have decided to try the filter approach.</P>
<P>The Experiment:</P>
<P>1. Create a meta-class SimpleDelegation</P>
<P>2. add a filter sdFilter to this meta-class</P>
<P>3. add an instproc setDelegate</P>
<P>4. Create classes A and B using SimpleDelegate</P>
<P>5. Create class C using Class</P>
<P>6. A has as delegate(instvar) an object of class B;</P>
<P>B has as delegate an object of class C</P>
<P>7. A,B and C has a method "m" defined</P>
<P>The Problem: (Using Windows binary ver 0.85)</P>
<P>I extended Prof. Neumann's code to handle above</P>
<P>and it works.(see Code1 below)</P>
<P>My experiment(Code 2) works only for the following</P>
<P>cases(that I tested):</P>
<P>1. A,B and C has a method "m".</P>
<P>2. The instvar delegate removed from B</P>
<P>It does not work when I rename the method</P>
<P>"m" in class C to "m2".</P>
<P>In this case I expect an object of class B to</P>
<P>execute "m" but instead I get an object of class</P>
<P>A executing "m" instead.</P>
<P>I would be grateful for any pointers to resolve</P>
<P>this problem.</P>
<P>Also I want to try to implement delegation as</P>
<P>described by Prof. Lieberman(OOPSLA 1986 paper).</P>
<P>Will be grateful for any pointers on this also.</P>
<P>...............</P>
<P>Code1: Prof Neumann's code inelegantly extended</P>
<P>Class A -parameter delegate</P>
<P>A instproc handleDelegation {result} {</P>
<P>if {[[self] exists delegate]} {</P>
<P>set context [::info level -1]</P>
<P>#look for method in delegated object</P>
<P>if {[[[self] set delegate] procsearch [lindex $context 0]] !=3D "" } =
{</P>
<P>::upvar $result y</P>
<P>set y [eval [[self] set delegate] $context]</P>
<P>return 1</P>
<P>}</P>
<P>}</P>
<P>return 0</P>
<P>}</P>
<P>A instproc m {x} {</P>
<P>if {[[self] handleDelegation r]} {</P>
<P>return $r</P>
<P>} else {</P>
<P>puts "[self] [self class] [self proc] $x";</P>
<P>return [next]</P>
<P>}</P>
<P>}</P>
<P>Class B -parameter delegate</P>
<P>B instproc handleDelegation {result} {</P>
<P>if {[[self] exists delegate]} {</P>
<P>set context [::info level -1]</P>
<P>#look for method in delegated object</P>
<P>if {[[[self] set delegate] procsearch [lindex $context 0]] !=3D "" } =
{</P>
<P>::upvar $result y</P>
<P>set y [eval [[self] set delegate] $context]</P>
<P>return 1</P>
<P>}</P>
<P>}</P>
<P>return 0</P>
<P>}</P>
<P>B instproc m {x} {</P>
<P>if {[[self] handleDelegation r]} {</P>
<P>return $r</P>
<P>} else {</P>
<P>puts "[self] [self class] [self proc] $x";</P>
<P>return [next]</P>
<P>}</P>
<P>}</P>
<P>Class D</P>
<P>D instproc m2 {x} {</P>
<P>puts "[self] [self class] [self proc] $x"</P>
<P>next</P>
<P>return [expr {$x*2 + [[self] set v]}]</P>
<P>}</P>
<P>D d1</P>
<P>d1 set v 100</P>
<P>B b1 -delegate d1</P>
<P>A a1 -delegate b1</P>
<P>puts "result =3D [a1 m 123]"</P>
<P>...............................................</P>
<P>Code2: My Try using filters</P>
<P>#create SimpleDelegation as a meta-class</P>
<P>Class SimpleDelegation -superclass Class</P>
<P>SimpleDelegation instproc sdFilter args {</P>
<P>set method [self calledproc]</P>
<P>if {[[self] exists delegate]} {</P>
<P>set del [[self] set delegate]</P>
<P>#if delegate has method then dispatch it.</P>
<P>if {[$del procsearch $method] !=3D ""} {</P>
<P>return [eval [$del $method $args]]</P>
<P>} </P>
<P>return [next];</P>
<P>}</P>
<P>}</P>
<P>SimpleDelegation instproc init args {</P>
<P>[self] filterappend [self class]::sdFilter</P>
<P>next</P>
<P>[self] instproc setDelegate {d} {</P>
<P>[self] set delegate $d</P>
<P>}</P>
<P>}</P>
<P>SimpleDelegation A -parameter delegate</P>
<P>SimpleDelegation B -parameter delegate</P>
<P> </P>
<P>A instproc m {x} {</P>
<P>puts "[self] [self class] [self proc] $x"</P>
<P>return [next]</P>
<P>}</P>
<P>B instproc m {x} {</P>
<P>puts "[self] [self class] [self proc] $x"</P>
<P>next</P>
<P>return [expr {$x*2 + [[self] set v]}]</P>
<P>}</P>
<P>Class C</P>
<P>#method "m" renamed to "m2" here.</P>
<P>C instproc m2 {x} {</P>
<P>puts "[self] [self class] [self proc] $x"</P>
<P>next</P>
<P>return [expr {$x*3 + [[self] set v]}]</P>
<P>}</P>
<P>A a</P>
<P>B b</P>
<P>a setDelegate b</P>
<P>b set v 100</P>
<P>C c</P>
<P>b setDelegate c</P>
<P>c set v 100</P>
<P>puts "result =3D [a m 123]"</P>
<P>..................................................</P>
<P>Regards,</P>
<P>Sheik Yussuff</P>
<P>email: sheik@carib-link.net</P></FONT></DIV></BODY></HTML>
------=_NextPart_000_000B_01C107B7.B25AF6C0--