How to copy a method from one class to another

Discussion in 'Ruby' started by Sam Kong, Sep 25, 2006.

  1. Sam Kong

    Sam Kong Guest

    Hi Rubyists,

    Is there a way to copy an instance method from one class to another?

    class C1
    def f
    p self.class
    end
    end

    class C2
    end

    Now I want C2 to have f method so that I can call C2.new.f.

    Thanks.

    Sam
     
    Sam Kong, Sep 25, 2006
    #1
    1. Advertising

  2. On Tue, Sep 26, 2006 at 01:10:17AM +0900, Sam Kong wrote:
    > Hi Rubyists,
    >
    > Is there a way to copy an instance method from one class to another?
    >
    > class C1
    > def f
    > p self.class
    > end
    > end
    >
    > class C2
    > end
    >
    > Now I want C2 to have f method so that I can call C2.new.f.
    >

    You can inherit.

    class C2 < C1
    end

    Or you can make C1 a module

    module C1
    def f
    p self.class
    end
    end

    class C2
    include C1
    end
     
    Logan Capaldo, Sep 25, 2006
    #2
    1. Advertising

  3. Sam Kong

    Sam Kong Guest

    Sam Kong wrote:
    > Hi Rubyists,
    >
    > Is there a way to copy an instance method from one class to another?
    >
    > class C1
    > def f
    > p self.class
    > end
    > end
    >
    > class C2
    > end
    >
    > Now I want C2 to have f method so that I can call C2.new.f.


    OK. I need to describe what I want.
    Actually this problem is rather imaginary than practical.
    While solving some other problem, this question came into my mind.
    Normally, I would use inheritance or mix-in or maybe delegation.
    This question is "What if...?"

    Let's say that there's a class (C1) in a library and I'm building my
    own class hierarchy including C2 (class C2 < SomeOtherClass).
    In such a case, Inheritance or mix-in is not an option.
    However, I want to add a method of C1 into my C2.
    As someone jokingly mentioned, I can copy the source code.
    Let's assume that the method is implemented in C and we don't have the
    source.

    Can we still copy(or reuse) the method?

    Sam
     
    Sam Kong, Sep 25, 2006
    #3
  4. Sam Kong

    MonkeeSage Guest

    Sam Kong wrote:
    > Let's say that there's a class (C1) in a library and I'm building my
    > own class hierarchy including C2 (class C2 < SomeOtherClass).
    > In such a case, Inheritance or mix-in is not an option.


    Unless I misunderstand, a mixin is fine:

    module C1
    def f
    p self.class
    end
    end

    class C2; end

    class C3 < C2
    include C1
    end

    C3.new.f # => "C3"

    Regards,
    Jordan
     
    MonkeeSage, Sep 25, 2006
    #4
  5. Sam Kong

    Verno Miller Guest

    Verno Miller, Sep 25, 2006
    #5
  6. Sam Kong

    Sam Kong Guest

    Hi Jordan,

    Jordan Callicoat wrote:
    > Sam Kong wrote:
    >> Let's say that there's a class (C1) in a library and I'm building my
    >> own class hierarchy including C2 (class C2 < SomeOtherClass).
    >> In such a case, Inheritance or mix-in is not an option.

    >
    > Unless I misunderstand, a mixin is fine:
    >
    > module C1
    > def f
    > p self.class
    > end
    > end


    Unfortunately, C1 is already a class.

    Sam

    --
    Posted via http://www.ruby-forum.com/.
     
    Sam Kong, Sep 25, 2006
    #6
  7. Sam Kong

    Sam Kong Guest

    Hi Verno,

    Verno Miller wrote:
    >>Posted by Sam Kong
    >>on 25.09.2006 18:11
    >>
    >> Hi Rubyists,
    >>
    >> Is there a way to copy an instance method from one class to another?

    >
    >
    > How about using something like "inheritance and super function"?
    >
    > http://www.ruby-forum.com/topic/81049


    But C1 and C2 are in different class hierarchies.
    C2 is not a kind of C1.
    What I'm trying to do is to copy(or reuse) the implementation of another
    class in a different hierarchy.

    Sam

    --
    Posted via http://www.ruby-forum.com/.
     
    Sam Kong, Sep 25, 2006
    #7
  8. Sam Kong

    Sam Kong Guest

    Hi Jeffrey,

    Jeffrey Schwab wrote:

    > If the method only exists in a library class, how do you know what it
    > would do to your class? It sounds like the best way to get the effect
    > you want might be the same thing you would do in C++ or Java, viz. to
    > let C2 have a member of type C1, and forward method calls to the member
    > object according to the "Law" of Demeter.


    Yes, I think you're entirely right on this.
    If C2 doesn't know how C1#f is implemented, it's no used copying the
    method's implementation or even copying the implementation won't work
    in C2's context.
    Now I know that my imaginary problem was totally non-sense.

    Thank you for enlightening me.

    Sam
     
    Sam Kong, Sep 25, 2006
    #8
  9. MonkeeSage wrote:
    > Sam Kong wrote:
    >
    >> Let's say that there's a class (C1) in a library and I'm building my
    >> own class hierarchy including C2 (class C2 < SomeOtherClass).
    >> In such a case, Inheritance or mix-in is not an option.
    >>

    >
    > Unless I misunderstand, a mixin is fine:
    >

    This wouldn't work in the situation Sam describes:

    class Rubyforge::C1 # for example in some rubyforge library
    def interesting_method
    if @foo > 3
    @bar += 2
    else
    @baz /= 2
    end
    end
    end

    Sam wonders how to call interesting_method from his class C2, that
    cannot inherit
    from C1, because it already inherits from SomeOtherClass:

    class C2 < SomeOtherClass
    def my_method
    interesting_method # ???
    end
    end

    This isn't possible in Ruby, because of single inheritance and the fact
    that Sam doesn't control the rubyforge library and thus cannot create a
    module to include in C2. The only way to get interesting_method's
    functionality into C2 is to copy & paste it.

    If there was a way in Ruby to do that like:

    class C2 < SomeOtherClass
    include Rubyforge::C1.to_module:)interesting_method)

    def my_method
    interesting_method
    end
    end

    This would introduce a tight coupling between C2 and C1 on the same
    level like inheritance would do. In some way it would be equivalent to
    real multiple inheritance. Now the author of C1 can break your code by
    refactoring e. g.:

    class Rubyforge::C1 # for example in some rubyforge library
    def interesting_method
    if @foo > 3
    add_two
    else
    @baz /= 2
    end
    end

    private

    def add_two
    @bar += 2
    end
    end

    I was in the same situation and ended up copying & pasting. I wished at
    the time, that it would have been possible to just import those methods,
    even if it meant that I might ending up shooting myself into the foot.

    There is an additional problem, that occurs when someone attempts to
    import methods from a Ruby class implemented in C, that uses a macro
    like RSTRING(foo)->len. In these cases it would be possible to trigger a
    Ruby segmentation fault by calling those methods. Of course it would
    perhaps be possible to mark C implemented methods and let Ruby refuse to
    export them. This would at least cause an ordinary exception during
    class loading time.

    --
    Florian Frank
     
    Florian Frank, Sep 25, 2006
    #9
  10. Sam Kong wrote:
    > If the method only exists in a library class, how do you know what it
    > would do to your class? It sounds like the best way to get the effect
    > you want might be the same thing you would do in C++ or Java, viz. to
    > let C2 have a member of type C1, and forward method calls to the member
    > object according to the "Law" of Demeter.
    >

    If this is possible, it is a better solution of course. I think in
    general it's better to use delegation than to use inheritance for code
    sharing purposes, using modules is maybe on par with delegation.
    >
    > Yes, I think you're entirely right on this.
    > If C2 doesn't know how C1#f is implemented, it's no used copying the
    > method's implementation or even copying the implementation won't work
    > in C2's context.
    > Now I know that my imaginary problem was totally non-sense.
    >
    > Thank you for enlightening me.
    >

    Ok, let me switch off the light again. ;) You would read the source code
    before you do it and decide if you can prepare instance variables and
    methods in the required way. I would call that "internal duck typing".
    Of course this would make it necessary to study the source code of C1 to
    find out what exactly it does. But this isn't so different from what you
    have to do if you want to inherit from the class (especially in Ruby).

    --
    Florian Frank
     
    Florian Frank, Sep 25, 2006
    #10
  11. Sam Kong

    MonkeeSage Guest

    Florian Frank wrote:
    > This wouldn't work in the situation Sam describes:


    Ah-ha. I'm kind of slow. ;)

    Regards,
    Jordan
     
    MonkeeSage, Sep 25, 2006
    #11
  12. Sam Kong

    Sam Kong Guest

    Hi Florian,

    Florian Frank wrote:
    > MonkeeSage wrote:
    > > Sam Kong wrote:
    > >
    > >> Let's say that there's a class (C1) in a library and I'm building my
    > >> own class hierarchy including C2 (class C2 < SomeOtherClass).
    > >> In such a case, Inheritance or mix-in is not an option.
    > >>

    > >
    > > Unless I misunderstand, a mixin is fine:
    > >

    > This wouldn't work in the situation Sam describes:
    >
    > class Rubyforge::C1 # for example in some rubyforge library
    > def interesting_method
    > if @foo > 3
    > @bar += 2
    > else
    > @baz /= 2
    > end
    > end
    > end
    >
    > Sam wonders how to call interesting_method from his class C2, that
    > cannot inherit
    > from C1, because it already inherits from SomeOtherClass:
    >
    > class C2 < SomeOtherClass
    > def my_method
    > interesting_method # ???
    > end
    > end
    >
    > This isn't possible in Ruby, because of single inheritance and the fact
    > that Sam doesn't control the rubyforge library and thus cannot create a
    > module to include in C2. The only way to get interesting_method's
    > functionality into C2 is to copy & paste it.
    >
    > If there was a way in Ruby to do that like:
    >
    > class C2 < SomeOtherClass
    > include Rubyforge::C1.to_module:)interesting_method)
    >
    > def my_method
    > interesting_method
    > end
    > end
    >
    > This would introduce a tight coupling between C2 and C1 on the same
    > level like inheritance would do. In some way it would be equivalent to
    > real multiple inheritance. Now the author of C1 can break your code by
    > refactoring e. g.:
    >
    > class Rubyforge::C1 # for example in some rubyforge library
    > def interesting_method
    > if @foo > 3
    > add_two
    > else
    > @baz /= 2
    > end
    > end
    >
    > private
    >
    > def add_two
    > @bar += 2
    > end
    > end
    >
    > I was in the same situation and ended up copying & pasting. I wished at
    > the time, that it would have been possible to just import those methods,
    > even if it meant that I might ending up shooting myself into the foot.
    >
    > There is an additional problem, that occurs when someone attempts to
    > import methods from a Ruby class implemented in C, that uses a macro
    > like RSTRING(foo)->len. In these cases it would be possible to trigger a
    > Ruby segmentation fault by calling those methods. Of course it would
    > perhaps be possible to mark C implemented methods and let Ruby refuse to
    > export them. This would at least cause an ordinary exception during
    > class loading time.
    >
    > --
    > Florian Frank


    I think you're understanding my problem very correctly.
    My need was sort of like multiple inheritance which is not supported in
    Ruby.
    Mix-in is the right way in Ruby.
    However, for mix-in, all things should be designed before
    implementation.
    If you want to reuse some part of a class, there's no easy way and
    probably it's not recommended like you said it's tight-coupling.

    Thank you for your time and expertise.

    Sam
     
    Sam Kong, Sep 25, 2006
    #12
  13. On 9/25/06, Sam Kong <> wrote:

    >
    > I think you're understanding my problem very correctly.
    > My need was sort of like multiple inheritance which is not supported in
    > Ruby.


    And even in a language like C++ which supports multiple inheritance,
    you can't pick and choose which functions you inherit.

    In fact, it's even harder because, unlike a dynamic language like
    Ruby, where inheritance and mix-in is used only to compose
    implementation, in a strongly typed language they also are the
    mechanism of type composition.

    It's this tight-coupling of implementation and specification which
    distinguishes the two approaches.

    And it's one good reason why Ruby is NOT C++, nor is it Java, and one
    of the reasons so many things seem to be easier in Ruby once you get
    acclimatized.

    > Mix-in is the right way in Ruby.
    > However, for mix-in, all things should be designed before
    > implementation.


    Not necessarily before, but in concert with, it's called iterative
    design, the design evolves as you learn more about the problem by
    implementing it.

    Another difference in the strongly typed vs. dynamic languages is the
    implications of refactoring. In a dynamic language it's more like
    rearranging furniture, while in a strongly-type one it's more like
    solving a 15-puzzle.

    --
    Rick DeNatale

    My blog on Ruby
    http://talklikeaduck.denhaven2.com/
     
    Rick DeNatale, Sep 25, 2006
    #13
  14. Hi,

    In message "Re: How to copy a method from one class to another"
    on Tue, 26 Sep 2006 05:15:20 +0900, "Sam Kong" <> writes:

    |Mix-in is the right way in Ruby.
    |However, for mix-in, all things should be designed before
    |implementation.

    If you are not allowed to modify existing classes. Most of the cases
    rewriting

    class C1
    def f
    p self.class
    end
    end

    to

    module M1
    def f
    p self.class
    end
    end

    class C1
    include M1
    end

    class C2
    include M1
    end

    is trivial. You don't need to design everything before
    implementation, but just have to evolve classes.

    If you are not allowed to modify pre-existing class, you need to use
    some kind of delegation.

    matz.
     
    Yukihiro Matsumoto, Sep 25, 2006
    #14
    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. Stewart Midwinter
    Replies:
    5
    Views:
    344
  2. Replies:
    3
    Views:
    966
    Roedy Green
    Jan 28, 2008
  3. marekw2143
    Replies:
    3
    Views:
    1,398
    marekw2143
    Jul 25, 2009
  4. Chuck Remes
    Replies:
    3
    Views:
    210
    hemant
    Aug 12, 2010
  5. Dan Stromberg
    Replies:
    1
    Views:
    97
    Steven D'Aprano
    Jun 7, 2014
Loading...

Share This Page