Custom method_missing doesn't trap super call

Absolutely. I kind of “discovered” delegation too, and found it gives you a
great way to build objects out of components - much more flexible than
subclassing, and neatly sidesteps a lot of philosophical issues with
subclassing too.

Cheers,

Brian.

···

On Tue, Jul 15, 2003 at 07:36:13PM +0900, Richard Dale wrote:

It looks like you have reinvented the delegator pattern:
http://www.rubycentral.com/book/lib_patterns.html

Cheers,

Brian.

Well crap, wouldn’t you know… I guess I need to do some more exploring
through Ruby resources.
But thanks - I’ll experiment with the delegator suggestions - I think this
is a fun problem to try and solve somehow…

Hi,

···

In message “Re: Custom method_missing doesn’t trap super call” on 03/07/16, Yukihiro Matsumoto matz@ruby-lang.org writes:

I’ve just tried 1.6.8, a more recent stable version of 1.6.8 and 1.8 preview
1 on Yellow Dog Linux 3.0 and none of them trap the super call. I tried
1.6.7 on Mac OS X and that was the same. So is it something to do with
PowerPC I wonder? This is the version info from gcc if that’s relevant:

Hmm, I don’t have any powerpc machine at hand. Let me see though.

After a short investigation, it found out to be a bug. It’s fixed in
the recent 1.8.0 (after 2003-06-03).

						matz.

Brian Candler wrote:

It looks like you have reinvented the delegator pattern:
http://www.rubycentral.com/book/lib_patterns.html

Cheers,

Brian.

Well crap, wouldn’t you know… I guess I need to do some more
exploring through Ruby resources.
But thanks - I’ll experiment with the delegator suggestions - I think
this is a fun problem to try and solve somehow…

Absolutely. I kind of “discovered” delegation too, and found it gives you
a great way to build objects out of components - much more flexible than
subclassing, and neatly sidesteps a lot of philosophical issues with
subclassing too.
I just tried adding this onto the end of the Example 2 of delegation in
Programming Ruby (page 468):

class FooBar < TicketOffice
def try_delegate_to_super()
puts “In try_delegate_to_super”
super
end
end

to = FooBar.new
puts to.sellTicket
to.try_delegate_to_super

So the superclass of FooBar is a delegator. When I ran it I got the
following output:

ruby trydelegate2.rb
Here is a ticket
In try_delegate_to_super
trydelegate2.rb:33:in try_delegate_to_super': super: no superclass method try_delegate_to_super’ (NameError)
from trydelegate2.rb:39

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.

– Richard

···

On Tue, Jul 15, 2003 at 07:36:13PM +0900, Richard Dale wrote:

Yukihiro Matsumoto wrote:

Hi,

I’ve just tried 1.6.8, a more recent stable version of 1.6.8 and 1.8
preview 1 on Yellow Dog Linux 3.0 and none of them trap the super call.
I tried 1.6.7 on Mac OS X and that was the same. So is it something to
do with PowerPC I wonder? This is the version info from gcc if that’s
relevant:

Hmm, I don’t have any powerpc machine at hand. Let me see though.

After a short investigation, it found out to be a bug. It’s fixed in
the recent 1.8.0 (after 2003-06-03).
Brilliant! I’ll switch to that version. Thanks for the help.

– Richard

···

In message “Re: Custom method_missing doesn’t trap super call” > on 03/07/16, Yukihiro Matsumoto matz@ruby-lang.org writes:

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:

···

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.


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.

P.S. I forgot the issue about ‘super’ which had been raised before, but when
you do explicit delegation the problem vanishes:

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 meth1
puts “meth1 in #{self.class}”
@sup.meth1 # <-----
end
end

c = Bar.new
c.meth1

#>>meth1 in Bar
#>>meth1 in Foo

Of course you’re not limited to one ‘parent’ object; you can decide to pass
to one or more objects which you hold a reference to.

Regards,

Brian.

···

On Tue, Jul 15, 2003 at 11:48:48PM +0900, Brian Candler wrote:

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: