[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