Have a look at this. Run it as is, then unremark the comment section.
Something strange is a foot here.
Brownings the source of the Delegator.rb is becomes clear that
it is not mend to be deal with this kind of abuse - also your
example is obscured by a superfluous block usage.
require 'delegate'
M = Module.new {
def bracket
p "come on"
end
module M
def bracket
p "come on"
end
end
class SD < SimpleDelegator
def initialize( obj )
super( obj )
s = (class << self ; self ; end)
s.class_eval { include M }
[Trans <transfire@gmail.com>, 2005-04-25 02.04 CEST]
> Have a look at this. Run it as is, then unremark the comment section.
> Something strange is a foot here.
[ snip example ]
> # my results
> # w/ comment : "hello"
> # w/o comment : "come on"
First, methods in the Delegator class (or subclass) are not forwarded:
I might add that (in your code, which I stupidly snipped), the code to
forward #bracket to the object was already done when the module was
included.
Perhaps I should point out that the strange thing about this is that
when the #bracket method in SD is NOT defined, then the module included
in the idioclass (singleton) is not called as one would expect it to
be. But when you add #bracket into SD, it "suddenly" works as it
should, and subsequently by passes the #bracket method just defined!
Perhaps I should point out that the strange thing about this is that
when the #bracket method in SD is NOT defined, then the module included
in the idioclass (singleton) is not called as one would expect it to
be. But when you add #bracket into SD, it "suddenly" works as it
should, and subsequently by passes the #bracket method just defined!
You really have to look at the source code in delegator.rb.
Instantiation creates a singleton method for all forwarded
methods - However some methods are not forwarded
(preserved) for example when they already defined in the
Delegator sub class. Now combine this with the following
behavior
···
---
module A
def foo
"subordinate"
end
end
class << a = Object.new
def foo
"dominate"
end
include A
end
p a.foo # dominate
--
and you have your explanation
Perhaps I should point out that the strange thing about this is that
when the #bracket method in SD is NOT defined, then the module included
in the idioclass (singleton) is not called as one would expect it to
be. But when you add #bracket into SD, it "suddenly" works as it
should, and subsequently by passes the #bracket method just defined!
Ok... another try to explanation. I think I know what part of information
you were missing.
1.
class C
include M
def x
end
end
If M defines x, C#x will not be overriden, ok? You oversaw this, I think.
2.
class X; def b; puts "x.b"; end
class SD < SimpleDelegator
def initialize
super # here self.b is defined to forward to X#b (1)
(class<<self;self;end).class_eval{include M}
# doesn't matter if M defines #b,
# self.b is already defined and won't be
# overriden (2). self.b forwards to X#b.
end
# def b
# puts "sd.b"
# end
# but if you uncomment the lines above, (1) doesn't happen (see my previous
# message), so (2) do add #b to the singleton class, and since methods are
# first searched in the singleton class, this #b will be called instead of
# SD#b.
end
Perhaps I should point out that the strange thing about this is that
when the #bracket method in SD is NOT defined, then the module included
in the idioclass (singleton) is not called as one would expect it to
be. But when you add #bracket into SD, it "suddenly" works as it
should, and subsequently by passes the #bracket method just defined!
For the record I included a small modification of delegate.rb which matches
your expectation.
Thanks. I see what you're both syaing now. That's too bad in that it
doesn't help my use case. In a way I consider this a bug. Although is
understandable why it does this. I see what I can do to get around it,
better yet I'll look at delegate.rb to see if there's a way to take
this into account. Perhpas make it check for singleton methods too.
Okay, now I'm trying to better understand how delegate.rb works b/c I
would like to reuse the principle behind it elsewhere. But I don't
understand one thing. How is self being redirected?
class SD < SimpleDelegator
def bracket
p self
end
end
class C
end
c = C.new
sd = SD.new(c)
sd.bracket
produces
#<C:0x40329350>
How does self become c in the context of sd? I don't see how
delegate.rb achieves this.