[Xotcl] implementing delegation in Xotcl?

Gustaf Neumann Gustaf.Neumann@wu-wien.ac.at
Mon, 18 Dec 2000 13:35:55 +0100 (CET)


>>>>> "CL" == Catherine Letondal <letondal@pasteur.fr> writes:
CL> Hi,
CL> I have a very philosophical question :-) 
CL> I would like to replace inheritance by delegation for some
CL> classes' instances.

CL> e.g:
CL> 	Class C -parameter {delegate}	# instead of Class C -superclass D
CL> 	C c -delegate a

CL> where a is an object of another class, say class A.

CL> Delegation means that:
CL> - next should call the delegate's proc/instproc
CL> - set, instvar would give access to delegate's variables
CL> (this is one of the classical delegation mechanisms/behaviour I believe?)


 Dear Catherine,

 Your definition is not the standard definition of delegation, since
 delegation is not related with the ideas of "next". Informally,
 delegation means: don't do everything by your[self], use another
 object to help you. Normally, delegation is pretty much hardwired to
 the code. 

 What you are trying to do is certainly very interesting. What you are
 facing is however, the "inverse self problem" (Lieberman observed,
 that through delegation, you easily loose the [self]-reference to the
 callee, the method called via delegation has a different [self]; by
 the means of mixins or filters, we tried to find alternate ways to
 achieve, what delegation does, but now you seem to want delegation,
 and you use filters and mixins, and you wonder how to get the self of
 the delegate ... therefore i called the problem "inverse self
 problem"). Somehow i doubt that you will be happy just by using
 instvars in the delegate, i assume you want real delegation.

 The problem is that by using "next", "mixins" etc. you do not change
 the active object ([self]), which is certainly quite an important
 assumption. I have to be convinced that this is too limited.

 Below is a simple implementation, which can be made nicer by using
 mixins or filters, but which is quite easy to understand and could
 help you as a starting point. Most likely, you will want to use
 "handleDelegation" for all methods, therefor a filter would be
 appropriate, but maybe, you want to try delegation for a set of
 methods, therefor you could use instmixins

 Suppose, an object a1 of class A wants to call a method "m". Method m
 has a stub for "m" that checks, whether it can delegate it (to object
 d1 of D) and delegates it if possible, otherwise it handles it by
 itself.

 Note, that this works fine without to much interference with the
 mixins/subclasses/... for A, a1, D, d1, instvars pose no problems,
 etc. It is fairly trivial to extend this program to handle multiple
 delegation objects...

 best regards
-gustaf

========================================================================= 

Class A -parameter delegate
A instproc handleDelegation {result} {
  if {[[self] exists delegate]} {
    set context [::info level -1]
    # look for the called method in the delegated object
    if {[[[self] set delegate] procsearch [lindex $context 0]] != ""} {
      ::upvar $result r
      set r [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 D
D instproc m {x} {
  puts "[self] [self class] [self proc] $x"
  next
  return [expr {$x*2 + [[self] set v]}]
}

D d1
d1 set v 100
A a1 -delegate d1


puts "result=[a1 m 123]"
=========================================================================