How to copy a method from one class to another

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

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

···

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.

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.

Thanks.

Perhaps it would be better for you to describe the problem this idea would
address. If you need to have a shared method, maybe it would be better to
put it in a module and associate the module with any classes needing the
method. Or a parent-child relationship can be established between classes
to make a particular method available to more than one class.

···

--
Paul Lutus
http://www.arachnoid.com

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 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

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

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"?

···

--
Posted via http://www.ruby-forum.com/\.

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/\.

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

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. :wink: 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

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"?

Inheritance and super function - Ruby - Ruby-Forum

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/\.

Florian Frank wrote:

This wouldn't work in the situation Sam describes:

Ah-ha. I'm kind of slow. :wink:

Regards,
Jordan

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

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.

···

On 9/25/06, Sam Kong <sam.s.kong@gmail.com> wrote:

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Hi,

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.

···

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