From: Brian Candler Date: 2003-07-15T23:48:48+09:00 Subject: Re: Custom method_missing doesn't trap super call 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.