Brian Candler
7/15/2003 2:49:00 PM
On Tue, Jul 15, 2003 at 10:37:29PM +0900, Richard Dale wrote:
> So although the SimpleDelegate class doesn''t use method_missing (my ruby
> isn''t good enough to tell how it works yet), it isn''t possible to forward a
> message to super this way either.
But you can now forget about class hierarchies, and deal with delegation
hierarchies instead.
I find it''s simplest and most powerful to explicitly keep track of objects
you want to delegate to. Here''s a trivial example:
-------------------------------------------------------------------------
class Foo # the ''superclass''
def meth1
puts "meth1 in #{self.class}"
end
end
class Bar # the ''child'' class
def initialize
@sup = Foo.new
end
def meth2
puts "meth2 in #{self.class}"
end
def method_missing(msg,*args,&blk)
@sup.send(msg,*args,&blk)
end
end
c = Bar.new
c.meth1
c.meth2
#>> meth1 in Foo
#>> meth2 in Bar
-------------------------------------------------------------------------
The above example shows ''method_missing'' in class Bar to delegate to @sup -
you could also use SimpleDelegator with __setobj__ - but in practice I write
explicit delegation functions, i.e.
def meth1(*args)
@sup.meth1(*args)
end
This means I don''t have to worry about ''public'' and ''private'', because I
explicitly only allow certain messages through. Furthermore, this works
properly over DRb, which only forwards methods which are explicitly defined
in the receiver object (it won''t fall back to method_missing).
By building your application like this, you can choose to have multiple
objects to which you delegate - e.g. delegate some methods to one object and
some to another. You can write composite methods which use more than one
delegate object to perform their work. The delegate objects can be changed
dynamically at run-time too. You end up creating ''glue'' or ''facade'' objects
which make use of other objects to do their work, in a very natural way.
When I thought about it, I realised that subclassing and module mixins are
really just Ruby internal implementations of the delegator pattern. If that
built-in implementation does exactly what you need, then that''s OK; but if
you need more fine-grained control, you just implement the delegation
yourself.
Regards,
Brian.