[Xotcl] implementing delegation in Xotcl?
Catherine Letondal
letondal@pasteur.fr
Sun, 17 Dec 2000 23:13:34 +0100
Hi,
I have a very philosophical question :-)
I would like to replace inheritance by delegation for some classes' instances.
e.g:
Class C -parameter {delegate} # instead of Class C -superclass D
C c -delegate a
where a is an object of another class, say class A.
Delegation means that:
- next should call the delegate's proc/instproc
- set, instvar would give access to delegate's variables
(this is one of the classical delegation mechanisms/behaviour I believe?)
I have tried 3 methods, but neither work!
1) with a filter on C, which branch the methods calls to the appropriate location.
the filter is defined in init:
C filter CFilter
C instproc CFilter args {
::set m [[self] info calledproc]
[self] instvar delegate
if { ([C info instprocs $m] != "") || ([[self] info procs $m] != "") } {
puts "CFilter m=$m I do it myself"
next
} elseif { [info exists delegate] && ($m == "set" || $m == "instvar") } {
puts "CFilter m=$m I delegate it to $delegate"
eval $delegate $m $args
} elseif {[info exists delegate] && [[$delegate info class] info instprocs $m] != ""} {
puts "CFilter m=$m I delegate it to $delegate"
eval $delegate $m $args
} else {
puts "I dont know (m=$m), I call next"
next
}
}
2) with a mixin on c
in init:
[self] mixin [$delegate info class]
3) with both
=> problem with filter only (1) :
- next does not work the way I want (it does not call the delegates)
- set of delegates' variables works, but instvar don't
=> problem with mixin only (2)
- as the delegate's class is the mixin, it's it's methods which are always
called first (but I want the delegate's methods to be called only when
not existing for the class or when calling next)
- I need a method in the delegate's class for every method int the class
- delegate's variables are not available, of course (since I only use the
class of the delegate to inherit methods)
=> mixin+filter (3) (example below) :
- instvar does not work
Does someone have ideas and opinions about this? Has someone already tried?
I don't remeber having found something about it in Xotcl's papers (maybe I'm wrong?).
Thanks!
--
Catherine Letondal -- Pasteur Institute Computing Center
+-------------------------------------------------------------------------------------
Example of code for solution (3):
# delegation with mixins+filter
# object a of class A will be used as delegate for C
Class A
A instproc f1 args {
puts "A f1 I am: [self] from class: [[self] info class]"
}
A instproc f3 args {
puts "A f3 I am: [self] from class: [[self] info class]"
}
A a
a set x 10
Class C -parameter {delegate}
C instproc init args {
[self] instvar delegate
if {[info exists delegate] && [::Object isobject $delegate]} {
puts "adding [$delegate info class] as a mixin for [self]"
[self] mixin [$delegate info class]
puts "adding CFilter as a filter for [[self] info class]"
[[self] info class] filter CFilter
}
}
C instproc f2 args {
puts "C f2 I am: [self] from class: [[self] info class]"
}
C instproc f3 args {
puts "C f3 I am: [self] from class: [[self] info class]"
puts "calling next"
next
}
C instproc CFilter args {
::set m [[self] info calledproc]
if {$m == "CFilter"} {
next
}
[self] instvar delegate
if { ([C info instprocs $m] != "") || ([[self] info procs $m] != "") } {
puts "CFilter m=$m I do it myself"
next
} elseif { [info exists delegate] && ($m == "set" || $m == "instvar") } {
puts "CFilter m=$m I delegate it to $delegate"
eval $delegate $m $args
} elseif {[info exists delegate] && [[$delegate info class] info instprocs $m] != ""} {
puts "CFilter m=$m I delegate it to $delegate"
eval $delegate $m $args
} else {
puts "I dont know (m=$m), I call next"
next
}
}
C d -delegate a
d proc f4 args {
[self] instvar x
puts "f4 [self] x: $x"
}
Try:
d f1
d f2
d f3
d f4