[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

method_missing behaves differently when a method is called via reflection?

Brian Hartin

11/10/2006 10:09:00 PM

For certain methods, it seems to behave differently if called via
reflection. Consider the following example:

class Foo
def method_missing(method, *args, &block)
"#{method} called"
end
end

f = Foo.new

f.bar('a')

-> "bar called"

f.send(:bar, 'a')

-> "bar called"

f.open('a')

-> "open called"

f.send(:open, 'a')

Errno::ENOENT: No such file or directory - a
from (irb):8:in `initialize'
from (irb):8

----

I know that 'open' is a Kernel method, but I would have expected
f.open('a') and f.send(:open, 'a') to behave similarly - either call the
Kernel method or call method_missing. Does anyone know why they're
different?

Thanks,

Brian Hartin

****************************************************************************
This email may contain confidential material.
If you were not an intended recipient,
Please notify the sender and delete all copies.
We may monitor email to and from our network.
****************************************************************************

1 Answer

Jacob Fugal

11/10/2006 10:17:00 PM

0

On 11/10/06, Hartin, Brian <Brian.Hartin@pearson.com> wrote:
> For certain methods, it seems to behave differently if called via
> reflection. Consider the following example:
>
> class Foo
> def method_missing(method, *args, &block)
> "#{method} called"
> end
> end
>
> f = Foo.new
>
> f.bar('a')
>
> -> "bar called"
>
> f.send(:bar, 'a')
>
> -> "bar called"
>
> f.open('a')
>
> -> "open called"
>
> f.send(:open, 'a')
>
> Errno::ENOENT: No such file or directory - a
> from (irb):8:in `initialize'
> from (irb):8
>
> ----
>
> I know that 'open' is a Kernel method, but I would have expected
> f.open('a') and f.send(:open, 'a') to behave similarly - either call the
> Kernel method or call method_missing. Does anyone know why they're
> different?

All Kernel methods are private. Usually, a Kernel method is called in
procedural style (without a receiver) and since every object includes
Kernel, the private method is visible and called. But when there is an
explicit receiver ("receiver.method_name"), private methods are left
out of the lookup. So when you call f.open, the private Kernel#open is
masked and the unhandled method is passed on to method_missing.
Object#send, however, bypasses privacy restrictions so f.send(:open)
catches hold of Kernel#open and you get the error.

So, in short, it's a matter of: private w/ send vs. private w/o send

Jacob Fugal