View · Search · Index
No registered users in community xowiki
in last 10 minutes

[Xotcl] implementing delegation in Xotcl?

From: Catherine Letondal <letondal_at_pasteur.fr>
Date: 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