Overridding A Method Via A Mixin

Discussion in 'Ruby' started by Andrew Stewart, Jan 15, 2008.

  1. Hi Everyone,

    I believe one can add methods to a class by including a module but
    not override existing methods. Indeed Dr Nic said as much here:

    http://ruby.tie-rack.org/6/safely-overriding-method_missing-in-a-
    class-that-already-has-it/#comment-7

    Here's some code that demonstrates this.

    class Foo
    def answer
    42
    end
    end

    module Bar
    def answer
    "What was the question?"
    end

    def to_s
    "bar"
    end
    end

    Foo.send :include, Bar
    f = Foo.new
    f.answer # => 42, not "What was the question?"
    f.to_s # => "bar", not "#<Foo:0x731248>"


    Why aren't existing methods overridden? And where could I have
    looked to find out the answer for myself (perhaps somewhere in Ruby's
    source?)?

    Thanks and regards,
    Andy

    -------
    http://airbladesoftware.com
    Andrew Stewart, Jan 15, 2008
    #1
    1. Advertising

  2. On 15.01.2008 18:32, Andrew Stewart wrote:
    > Hi Everyone,
    >
    > I believe one can add methods to a class by including a module but
    > not override existing methods. Indeed Dr Nic said as much here:
    >
    > http://ruby.tie-rack.org/6/safely-overriding-method_missing-in-a-
    > class-that-already-has-it/#comment-7
    >
    > Here's some code that demonstrates this.
    >
    > class Foo
    > def answer
    > 42
    > end
    > end
    >
    > module Bar
    > def answer
    > "What was the question?"
    > end
    >
    > def to_s
    > "bar"
    > end
    > end
    >
    > Foo.send :include, Bar
    > f = Foo.new
    > f.answer # => 42, not "What was the question?"
    > f.to_s # => "bar", not "#<Foo:0x731248>"
    >
    >
    > Why aren't existing methods overridden? And where could I have
    > looked to find out the answer for myself (perhaps somewhere in Ruby's
    > source?)?


    Because of the position in the inheritance hierarchy:

    irb(main):001:0> module Bar;end
    => nil
    irb(main):002:0> class Foo
    irb(main):003:1> include Bar
    irb(main):004:1> end
    => Foo
    irb(main):005:0> Foo.ancestors
    => [Foo, Bar, Object, Kernel]

    Methods defined in Foo are always found before their counterparts in
    included modules. Consequently you can override super class methods
    with a module.

    Kind regards

    robert
    Robert Klemme, Jan 15, 2008
    #2
    1. Advertising

  3. On 15 Jan 2008, at 17:40, Robert Klemme wrote:
    > Because of the position in the inheritance hierarchy:
    >
    > irb(main):001:0> module Bar;end
    > => nil
    > irb(main):002:0> class Foo
    > irb(main):003:1> include Bar
    > irb(main):004:1> end
    > => Foo
    > irb(main):005:0> Foo.ancestors
    > => [Foo, Bar, Object, Kernel]
    >
    > Methods defined in Foo are always found before their counterparts
    > in included modules. Consequently you can override super class
    > methods with a module.


    Aha, of course. Thank you for the clear explanation.

    I really should have worked that one out myself!

    With regards,
    Andy Stewart

    -------
    http://airbladesoftware.com
    Andrew Stewart, Jan 15, 2008
    #3
  4. Andrew Stewart

    Jens Wille Guest

    hi andrew!

    Andrew Stewart [2008-01-15 18:32]:
    > I believe one can add methods to a class by including a module
    > but not override existing methods.

    well, you *can* override them explicitly:

    module Bar
    def self.included(base)
    methods_to_override = %w[answer]
    # or even <tt>instance_methods(false)</tt>

    methods_to_override.each { |method|
    base.send:)define_method, method, instance_method(method))
    }
    end
    end

    if that's what you want... ;-)

    cheers
    jens

    --
    Jens Wille, Dipl.-Bibl. (FH)
    prometheus - Das verteilte digitale Bildarchiv für Forschung & Lehre
    Kunsthistorisches Institut der Universität zu Köln
    Albertus-Magnus-Platz, D-50923 Köln
    Tel.: +49 (0)221 470-6668, E-Mail:
    http://www.prometheus-bildarchiv.de/
    Jens Wille, Jan 15, 2008
    #4
  5. On 15.01.2008 19:10, Andrew Stewart wrote:
    > On 15 Jan 2008, at 17:40, Robert Klemme wrote:
    >> Because of the position in the inheritance hierarchy:
    >>
    >> irb(main):001:0> module Bar;end
    >> => nil
    >> irb(main):002:0> class Foo
    >> irb(main):003:1> include Bar
    >> irb(main):004:1> end
    >> => Foo
    >> irb(main):005:0> Foo.ancestors
    >> => [Foo, Bar, Object, Kernel]
    >>
    >> Methods defined in Foo are always found before their counterparts
    >> in included modules. Consequently you can override super class
    >> methods with a module.

    >
    > Aha, of course. Thank you for the clear explanation.


    You're welcome!

    > I really should have worked that one out myself!


    Ah, no worries. Once in a while this just happens to all of us.

    Btw, you got a nice website there (with a typo on the vortex page *g*).

    Kind regards

    robert
    Robert Klemme, Jan 15, 2008
    #5
  6. Re: Ruby on Rails/mod_perl Developer - Free lunch on Fridays!

    Where is this at? This is one of the most vague job listings I've ever seen.

    I'm assuming Seattle?

    --Jeremy

    On Jan 15, 2008 1:29 PM, Scot H. Baker <> wrote:
    >
    > Are you a talented Ruby on Rails or mod_perl Developer looking for an
    > exciting opportunity? My client runs a leading enthusiasts
    > community/e-commerce site and they need your expertise to create new
    > features and functions related to social networking. This is a great
    > opportunity to work with a fun group and contribute to exciting
    > technology that's used by many!
    >
    > Qualifications:
    >
    > * Thorough understanding of object-oriented methodology
    > * Thorough understanding of MVC architectures
    > * Experience with coding database-backed web applications
    > * Expert knowledge in either mod_perl or Ruby on Rails
    > * Intermediate knowledge of a mod_perl templating language
    > * Intermediate CSS and Javascript skills
    > * Willingness to work in an Agile development environment
    > * Ability to clearly and concisely communicate technical ideas
    >
    > If you are interested or know someone that is interested please have
    > them email a resume as a Word attachment to or
    >
    >
    > Thanks!
    > Scot Baker
    > Technical Recruiting Manager
    > parker technical
    > 605 Fifth Avenue South -Suite 850- Seattle, WA 98104
    > | p: 206-652-1587 | f: 206-223-8227 |
    > c:206-915-9020
    > http://www.linkedin.com/in/scotbaker
    >
    >
    >
    >




    --
    http://www.jeremymcanally.com/

    My books:
    Ruby in Practice
    http://www.manning.com/mcanally/

    My free Ruby e-book
    http://www.humblelittlerubybook.com/

    My blogs:
    http://www.mrneighborly.com/
    http://www.rubyinpractice.com/
    Jeremy McAnally, Jan 15, 2008
    #6
  7. Andrew Stewart

    ara.t.howard Guest

    On Jan 15, 2008, at 10:32 AM, Andrew Stewart wrote:

    > Hi Everyone,
    >
    > I believe one can add methods to a class by including a module but
    > not override existing methods. Indeed Dr Nic said as much here:
    >
    > http://ruby.tie-rack.org/6/safely-overriding-method_missing-in-a-
    > class-that-already-has-it/#comment-7




    i personally avoid aliases like that - they stack when you double
    require or double include a module and throw into a loop. this kind
    of thing can be done safely and generically using a variable for the
    previous method that's protected from the gc and a lookup in the new
    method:



    cfp:~ > cat a.rb
    class A
    def foo
    p "A.foo"
    end
    end
    class B
    end

    module M
    NoGC = []

    def self.included other
    other.module_eval do
    if((foo = instance_method 'foo' rescue false))
    NoGC.push foo
    supra = "ObjectSpace._id2ref(#{ foo.object_id }).bind
    (self).call(*a, &b)"
    end
    eval <<-code
    def foo *a, &b
    #{ supra }
    p "M.foo"
    end
    code
    end
    end
    end

    A.send :include, M
    B.send :include, M

    A.new.foo
    B.new.foo


    cfp:~ > ruby a.rb
    "A.foo"
    "M.foo"
    "M.foo"


    this allows you to both override and super up, in any combination,
    with a method injected late into a class hierarchy


    kind regards


    a @ http://codeforpeople.com/
    --
    it is not enough to be compassionate. you must act.
    h.h. the 14th dalai lama
    ara.t.howard, Jan 15, 2008
    #7
  8. Andrew Stewart

    Glen Holcomb Guest

    Re: Ruby on Rails/mod_perl Developer - Free lunch on Fridays!

    [Note: parts of this message were removed to make it a legal post.]

    As long as it's close to a Soup Kitchen they have the free lunch thing
    covered.

    On Jan 15, 2008 12:19 PM, Jeremy McAnally <> wrote:

    > Where is this at? This is one of the most vague job listings I've ever
    > seen.
    >
    > I'm assuming Seattle?
    >
    > --Jeremy
    >
    > On Jan 15, 2008 1:29 PM, Scot H. Baker <> wrote:
    > >
    > > Are you a talented Ruby on Rails or mod_perl Developer looking for an
    > > exciting opportunity? My client runs a leading enthusiasts
    > > community/e-commerce site and they need your expertise to create new
    > > features and functions related to social networking. This is a great
    > > opportunity to work with a fun group and contribute to exciting
    > > technology that's used by many!
    > >
    > > Qualifications:
    > >
    > > * Thorough understanding of object-oriented methodology
    > > * Thorough understanding of MVC architectures
    > > * Experience with coding database-backed web applications
    > > * Expert knowledge in either mod_perl or Ruby on Rails
    > > * Intermediate knowledge of a mod_perl templating language
    > > * Intermediate CSS and Javascript skills
    > > * Willingness to work in an Agile development environment
    > > * Ability to clearly and concisely communicate technical ideas
    > >
    > > If you are interested or know someone that is interested please have
    > > them email a resume as a Word attachment to or
    > >
    > >
    > > Thanks!
    > > Scot Baker
    > > Technical Recruiting Manager
    > > parker technical
    > > 605 Fifth Avenue South -Suite 850- Seattle, WA 98104
    > > | p: 206-652-1587 | f: 206-223-8227 |
    > > c:206-915-9020
    > > http://www.linkedin.com/in/scotbaker
    > >
    > >
    > >
    > >

    >
    >
    >
    > --
    > http://www.jeremymcanally.com/
    >
    > My books:
    > Ruby in Practice
    > http://www.manning.com/mcanally/
    >
    > My free Ruby e-book
    > http://www.humblelittlerubybook.com/
    >
    > My blogs:
    > http://www.mrneighborly.com/
    > http://www.rubyinpractice.com/
    >
    >



    --
    "Hey brother Christian with your high and mighty errand, Your actions speak
    so loud, I can't hear a word you're saying."

    -Greg Graffin (Bad Religion)
    Glen Holcomb, Jan 15, 2008
    #8
  9. Andrew Stewart

    Robert Dober Guest

    On Jan 15, 2008 8:33 PM, ara.t.howard <> wrote:

    > this allows you to both override and super up, in any combination,
    > with a method injected late into a class hierarchy

    Actually whenever these issues come up I wonder why we still define
    methods in classes?
    Either, using pure Ruby implementening all functionality im Modules
    (with the dangerous pitfall of double inclusion, or just using Traits
    Composition would just end all of that kind of complexity) But even I
    do not use my Traits package, old habits are difficult to lose
    indeed....
    Cheers
    Robert
    --
    http://ruby-smalltalk.blogspot.com/

    ---
    Whereof one cannot speak, thereof one must be silent.
    Ludwig Wittgenstein
    Robert Dober, Jan 15, 2008
    #9
  10. On 15 Jan 2008, at 18:15, Jens Wille wrote:
    > well, you *can* override them explicitly:
    >
    > module Bar
    > def self.included(base)
    > methods_to_override = %w[answer]
    > # or even <tt>instance_methods(false)</tt>
    >
    > methods_to_override.each { |method|
    > base.send:)define_method, method, instance_method(method))
    > }
    > end
    > end
    >
    > if that's what you want... ;-)


    There's always a way! Thanks Jens, that's neat.

    Regards,
    Andy Stewart

    -------
    http://airbladesoftware.com
    Andrew Stewart, Jan 16, 2008
    #10
  11. On 15 Jan 2008, at 18:39, Robert Klemme wrote:
    > Btw, you got a nice website there (with a typo on the vortex page
    > *g*).


    Thanks! You are kind to say so.

    I can't find that typo though...are you pulling my leg? :)

    With regards,
    Andy Stewart

    -------
    http://airbladesoftware.com
    Andrew Stewart, Jan 16, 2008
    #11
  12. On 15 Jan 2008, at 19:33, ara.t.howard wrote:
    > i personally avoid aliases like that - they stack when you double
    > require or double include a module and throw into a loop. this
    > kind of thing can be done safely and generically using a variable
    > for the previous method that's protected from the gc and a lookup
    > in the new method:


    I see. That sounds much more sensible.

    > cfp:~ > cat a.rb
    > class A
    > def foo
    > p "A.foo"
    > end
    > end
    > class B
    > end
    >
    > module M
    > NoGC = []
    >
    > def self.included other
    > other.module_eval do
    > if((foo = instance_method 'foo' rescue false))
    > NoGC.push foo
    > supra = "ObjectSpace._id2ref(#{ foo.object_id }).bind
    > (self).call(*a, &b)"
    > end
    > eval <<-code
    > def foo *a, &b
    > #{ supra }
    > p "M.foo"
    > end
    > code
    > end
    > end
    > end
    >
    > A.send :include, M
    > B.send :include, M
    >
    > A.new.foo
    > B.new.foo
    >
    >
    > cfp:~ > ruby a.rb
    > "A.foo"
    > "M.foo"
    > "M.foo"
    >
    >
    > this allows you to both override and super up, in any combination,
    > with a method injected late into a class hierarchy


    Wonderful!

    I should confess that I haven't entirely convinced myself that I
    understand your construction of supra. Given that you have the
    unbound method in the foo variable, is the reason why you can't bind
    foo directly, perhaps like this:

    supra = "#{foo}.bind(self).call(*a, &b)"

    ...because there's no way to write the string so it eval's the way we
    want it to?

    Thank you for the enlightenment :)

    Regards,
    Andy Stewart

    -------
    http://airbladesoftware.com
    Andrew Stewart, Jan 16, 2008
    #12
  13. Andrew Stewart

    Todd Benson Guest

    On Jan 16, 2008 10:06 AM, Andrew Stewart <> wrote:
    >
    > On 15 Jan 2008, at 18:39, Robert Klemme wrote:
    > > Btw, you got a nice website there (with a typo on the vortex page
    > > *g*).

    >
    > Thanks! You are kind to say so.
    >
    > I can't find that typo though...are you pulling my leg? :)


    I think he was joking since Americans typically use "specialize" and
    "center" instead :)

    Todd
    Todd Benson, Jan 16, 2008
    #13
  14. On 16.01.2008 19:19, Todd Benson wrote:
    > On Jan 16, 2008 10:06 AM, Andrew Stewart <> wrote:
    >> On 15 Jan 2008, at 18:39, Robert Klemme wrote:
    >>> Btw, you got a nice website there (with a typo on the vortex page
    >>> *g*).

    >> Thanks! You are kind to say so.


    You're welcome! I really like the clean design. You know, I am more
    the "Braun" type than the "Hundertwasser" type. Also, I noticed you use
    Mongrel for hosting. :)

    >> I can't find that typo though...are you pulling my leg? :)

    >
    > I think he was joking since Americans typically use "specialize" and
    > "center" instead :)


    Nope. First, I am not American* and second, these are not the words I
    had in mind. The "offending" word is somewhere between "organised" and
    "David Allen's". To give an additional hint, it's spelled correct *and*
    wrong in the *same* paragraph. :)

    Cheers

    robert



    * Although I have to say that most English I am exposed to is probably
    American English. :)
    Robert Klemme, Jan 16, 2008
    #14
  15. Andrew Stewart

    Todd Benson Guest

    On Jan 16, 2008 1:39 PM, Robert Klemme <> wrote:
    > Nope. First, I am not American* and second, these are not the words I
    > had in mind.


    Got it. Easy to miss. Also, I assumed you were talking about the home page.

    cheers,
    Todd
    Todd Benson, Jan 16, 2008
    #15
  16. On 16 Jan 2008, at 19:39, Robert Klemme wrote:
    > The "offending" word is somewhere between "organised" and "David
    > Allen's". To give an additional hint, it's spelled correct *and*
    > wrong in the *same* paragraph. :)


    Got it. Quelle gaffe!

    I like to take pride in shunning automatic spell-checking...so I
    shouldn't be surprised when a fall follows :)

    Kind regards,
    Andy Stewart

    -------
    http://airbladesoftware.com
    Andrew Stewart, Jan 17, 2008
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. gane kol
    Replies:
    1
    Views:
    349
    Scott Allen
    Apr 15, 2005
  2. Roedy Green

    overridding factories.

    Roedy Green, Aug 24, 2003, in forum: Java
    Replies:
    0
    Views:
    359
    Roedy Green
    Aug 24, 2003
  3. Mac
    Replies:
    1
    Views:
    572
  4. Trans
    Replies:
    4
    Views:
    125
    Trans
    Aug 8, 2005
  5. Farrel Lifson

    Mixin a module method as a class method

    Farrel Lifson, Oct 18, 2006, in forum: Ruby
    Replies:
    9
    Views:
    116
    Trans
    Oct 19, 2006
Loading...

Share This Page