Copying methods from one class to another

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

···


T.

T. Onoma wrote:

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

I’d like to know the answer to this one, too, though I suspect there
isn’t going to be a way. If such a feature existed, then in order to be
safe in copying a method from one class to another, there should also be
a feature that allowed you to query which methods a method depends on,
and that can be a tough question to answer (perhaps even impossible,
though I couldn’t say that with confidence).

···


Jamis Buck
jgb3@email.byu.edu

ruby -h | ruby -e ‘a=;readlines.join.scan(/-(.)[e|Kk(\S*)|le.l(…)e|#!(\S*)/) {|r| a << r.compact.first };puts “\n>#{a.join(%q/ /)}<\n\n”’

At first it seemed like it would be easy, since Ruby is so dynamic --if I add
a method to a class, every object previously defined as that class instantly
has it. But then I discoverd that the super keyword appear “prebound” to its
superclass. Take a look at:

class C
def x
super
end
end

class C < C;
@aspect = true
def self.method_added(m)
meth = self.instance_method(m)
self.superclass.class_eval %Q{
remove_method(:#{m}) if method_defined?(:m)
define_method(:#{m}, meth)
}
remove_method(m)
end
end
c = C.new
c.x

I have satisfied the condition of the binding class being the same class type,
but nonetheless this code causes an infinite recursion on the super call.

So now I’m guessing the problem is one of closure.

···

On Tuesday 16 December 2003 05:23 am, Jamis Buck wrote:

T. Onoma wrote:

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

I’d like to know the answer to this one, too, though I suspect there
isn’t going to be a way. If such a feature existed, then in order to be
safe in copying a method from one class to another, there should also be
a feature that allowed you to query which methods a method depends on,
and that can be a tough question to answer (perhaps even impossible,
though I couldn’t say that with confidence).


T.

When I ran it I got:

redef.rb:7: warning: already initialized constant C
redef.rb:3:in x': super: no superclass method x’ (NoMethodError)
from redef.rb:19

David

···

On Tue, 16 Dec 2003, T. Onoma wrote:

At first it seemed like it would be easy, since Ruby is so dynamic --if I add
a method to a class, every object previously defined as that class instantly
has it. But then I discoverd that the super keyword appear “prebound” to its
superclass. Take a look at:

class C
def x
super
end
end

class C < C;
@aspect = true
def self.method_added(m)
meth = self.instance_method(m)
self.superclass.class_eval %Q{
remove_method(:#{m}) if method_defined?(:m)
define_method(:#{m}, meth)
}
remove_method(m)
end
end
c = C.new
c.x

I have satisfied the condition of the binding class being the same class type,
but nonetheless this code causes an infinite recursion on the super call.


David A. Black
dblack@wobblini.net

Thanks David, I forgot the most important part! Here, this one makes it even
more plain:

class C

don’t even need the def here

end

class C < C;
@aspect = true
def self.method_added(m)
meth = self.instance_method(m)
self.superclass.class_eval %Q{
remove_method(:#{m}) if method_defined?(:m)
define_method(:#{m}, meth)
}
self.remove_method(m)
end
end

class C # this is what I forgot: to add a method
def x
print “<”; super
end
end

c = C.new
c.x

···

On Tuesday 16 December 2003 02:51 pm, David A. Black wrote:

When I ran it I got:

redef.rb:7: warning: already initialized constant C
redef.rb:3:in x': super: no superclass method x’ (NoMethodError)
from redef.rb:19


T.

Sorry to step into the middle of a conversation, but what does this mean:

class C < C;

I think this is a wrong construction. It says create (or extend) class C,
which inherits from C.

Seems redundant.

Looking over the docs, I think your use of super is also wrong, because you
don’t really have a super class.

···


A principle is universal.
A rule is specific.
A law is invariable.
http://www.hacksaw.orghttp://www.privatecircus.com – KB1FVD

Hi –

···

On Tue, 16 Dec 2003, T. Onoma wrote:

On Tuesday 16 December 2003 02:51 pm, David A. Black wrote:

When I ran it I got:

redef.rb:7: warning: already initialized constant C
redef.rb:3:in x': super: no superclass method x’ (NoMethodError)
from redef.rb:19

Thanks David, I forgot the most important part! Here, this one makes it even
more plain:

class C

don’t even need the def here

end

class C < C;
@aspect = true
def self.method_added(m)
meth = self.instance_method(m)
self.superclass.class_eval %Q{
remove_method(:#{m}) if method_defined?(:m)
define_method(:#{m}, meth)
}
self.remove_method(m)
end
end

class C # this is what I forgot: to add a method
def x
print “<”; super
end
end

c = C.new
c.x

That code gives me:

redef.rb:5: warning: already initialized constant C
redef.rb:13:in method_added': private method remove_method’ called
for C:Class (NoMethodError)
from redef.rb:18

David


David A. Black
dblack@wobblini.net

Sorry to step into the middle of a conversation, but what does this mean:
class C < C;

He try to bypass the method binding : but ruby has seen this, and fatally
he has a problem :slight_smile:

Guy Decoux

Sorry to step into the middle of a conversation, but what does this mean:

class C < C;

class C

end

class B < C

end

C = B

No difference, except now we have two names for the same thing B and C. We
have just redefined the constant to point to a subclass of its old self. Not
really all that tricky, although it does seem like it with the short
notation.

I think this is a wrong construction. It says create (or extend) class C,
which inherits from C.

Seems redundant.

Looking over the docs, I think your use of super is also wrong, because you
don’t really have a super class.

Make more sense now?

···

On Tuesday 16 December 2003 04:33 pm, Hacksaw wrote:


T.

Agghhh…I sware I ran it before I posted it, hmm… oh, duh! I added the
self on remove_method. (Note to self: DO NOT touch up code for email posts
after putting them in email message!) Here, I promise this one “works” and
is more concise thanks to some other posts I was able to learn from.

class C
end

class C < C;
def self.method_added(m)
meth = self.instance_method(m)
self.superclass.send(:define_method, m, meth)
self.send(:remove_method, m)
end
end

class C
def x
print “<”; super
end
end

c = C.new
c.x

···

On Tuesday 16 December 2003 07:32 pm, David A. Black wrote:

class C

don’t even need the def here

end

class C < C;
@aspect = true
def self.method_added(m)
meth = self.instance_method(m)
self.superclass.class_eval %Q{
remove_method(:#{m}) if method_defined?(:m)
define_method(:#{m}, meth)
}
self.remove_method(m)
end
end

class C # this is what I forgot: to add a method
def x
print “<”; super
end
end

c = C.new
c.x

That code gives me:

redef.rb:5: warning: already initialized constant C
redef.rb:13:in method_added': private method remove_method’ called
for C:Class (NoMethodError)
from redef.rb:18


T.

No. Why would B and C be equal? B is a subclass of C. Specifically, methods
and variable defined in B are not reflected in C.

The only way that they are equal is that an inherited method in B should do
the same thing as in C. Same with inherited variables.

···

On Tuesday 16 December 2003 04:33 pm, Hacksaw wrote:

Sorry to step into the middle of a conversation, but what does this mean:

class C < C;

class C

end

class B < C

end

C = B

No difference, except now we have two names for the same thing B and C. We
have just redefined the constant to point to a subclass of its old self. Not
really all that tricky, although it does seem like it with the short
notation.

Make more sense now?


Silence is not silent.
http://www.hacksaw.orghttp://www.privatecircus.com – KB1FVD

      self.superclass.__send__(:define_method, m, meth)

Sincerely, what do you expect which such a program ?

Guy Decoux

That’s okay, I had the same difficulties understanding this at firs too. Let
back up a bit. Look at this:

A = “1”
B = “2”
A = B

What happens?

p A # => “2”

It’s the same thing for classes. I know it’s tempting to “over think” when
classes are being delt with, I did the very same thing before I understood
what was going on. But it really is that simple. After all, classes are
objects just like strings.

So lets do it again, but this time with less “syntatical sugar”:

A = Class.new
B = Class.new(A) # A is the superclass of B
A = B

All that’s happened is that A no longer points to its former self. Rather it
now points to the same thing B does. The old A still exists as the superclass
of B, but we no longer have a convienent constant to reference it by. Note
that constants in Ruby are rather variable. The only thing that is noticably
different is that Ruby spits out a warning saying we have redefined a
constant.

So, the short notation of

class A < A

is the same as:

A = Class.new(A)

and does the exact same thing as above, except that it dispenses with the go
between constant B. And is analogous to doing this with a string:

str = " A new string " + str

···

On Tuesday 16 December 2003 10:51 pm, Hacksaw wrote:

No. Why would B and C be equal? B is a subclass of C. Specifically, methods
and variable defined in B are not reflected in C.

The only way that they are equal is that an inherited method in B should do
the same thing as in C. Same with inherited variables.


T.

Essentially, combining two classes to behave as a single unit. The inner layer
is the core class (superclass) and the outer layer is the wrapper class
(subclass). The end-user deals with the wrapper, unknowingly that it is
bumping things up to the hidden superclass b/c includes and method additions
need to be in core class as usual.

But it is difficult to get pieces to go in right places. Too bad define_method
is not a pre-hook to method creation like append_features. We could have
cut’em off at the pass :wink:

···

On Wednesday 17 December 2003 11:01 am, ts wrote:

  self.superclass.__send__(:define_method, m, meth)

Sincerely, what do you expect which such a program ?


T.

So, the short notation of

class A < A

is the same as:

A = Class.new(A)

and does the exact same thing as above, except that it dispenses with the go
between constant B. And is analogous to doing this with a string:

str = " A new string " + str

Well, okay, you can do this. It strikes me that this is the equivalent of asking for a new ferrari, and then replacing it’s insides with another new ferrari.

Essentially, combining two classes to behave as a single unit. The inner layer
is the core class (superclass) and the outer layer is the wrapper class
(subclass). The end-user deals with the wrapper, unknowingly that it is
bumping things up to the hidden superclass b/c includes and method additions
need to be in core class as usual.

I've given the example

nasun% ruby -e 'p Array.superclass'
Object
nasun%

You really want to define the method #pop (which is actually in Array) in
Object ?

But it is difficult to get pieces to go in right places. Too bad define_method
is not a pre-hook to method creation like append_features. We could have
cut'em off at the pass :wink:

You don't prefer to have #become, this is will be faster if you just want
to crash ruby

Guy Decoux

This still does not answer the question of why? (At least for me), so
I’m jumping in here are asking it again!

When you can simply extend class A with any new method you need, why do
you want to create a subclass and pretend it is the class you started
with?

Regards

Ian

···

In message 200312161434.02097.transami@runbox.com, T. Onoma transami@runbox.com writes

On Tuesday 16 December 2003 10:51 pm, Hacksaw wrote:

No. Why would B and C be equal? B is a subclass of C. Specifically, methods
and variable defined in B are not reflected in C.

The only way that they are equal is that an inherited method in B should do
the same thing as in C. Same with inherited variables.

That’s okay, I had the same difficulties understanding this at firs too. Let
back up a bit. Look at this:

A = “1”
B = “2”
A = B

What happens?

p A # => “2”

It’s the same thing for classes. I know it’s tempting to “over think” when
classes are being delt with, I did the very same thing before I understood
what was going on. But it really is that simple. After all, classes are
objects just like strings.

So lets do it again, but this time with less “syntatical sugar”:

A = Class.new
B = Class.new(A) # A is the superclass of B
A = B

All that’s happened is that A no longer points to its former self. Rather it
now points to the same thing B does. The old A still exists as the superclass
of B, but we no longer have a convienent constant to reference it by. Note
that constants in Ruby are rather variable. The only thing that is noticably
different is that Ruby spits out a warning saying we have redefined a
constant.

So, the short notation of

class A < A

is the same as:

A = Class.new(A)

and does the exact same thing as above, except that it dispenses with the go
between constant B. And is analogous to doing this with a string:

str = " A new string " + str


Ian - posting to a Newsgroup. Please remove everything to reply.

Well, okay, you can do this. It strikes me that this is the equivalent
of asking for a new ferrari, and then replacing it’s insides with
another new ferrari.

Actually that’s what we’d like it to do, but it doesn’t. All existing
ferraris keep the same internals. But anyone who wants to buy a new
ferrari gets a new model.

Ian Hobson wrote:

This still does not answer the question of why? (At least for me), so
I’m jumping in here are asking it again!

When you can simply extend class A with any new method you need, why
do you want to create a subclass and pretend it is the class you
started with?

Regards

Ian

Well, I’m not really the right one to answer this, but I’ll try. My
understanding is that they are trying to implement method wrappers (the
whole AOP thing) using existing Ruby features (whereas matz’s slides
about Rite indicate a new syntax for method wrappers).

One of the things they are investigating is subclassing as a way of
wrapping methods. It’s a clever trick, and if it were possible to copy
methods from one class to another it might actually work. However, it
looks like you can’t do it this way.

Those who are “in the know”, please correct me if I’ve terribly
misstated anything…

···


Jamis Buck
jgb3@email.byu.edu

ruby -h | ruby -e ‘a=;readlines.join.scan(/-(.)[e|Kk(\S*)|le.l(…)e|#!(\S*)/) {|r| a << r.compact.first };puts “\n>#{a.join(%q/ /)}<\n\n”’

James’ answer is correct. We have been discussing Aspect Oriented Programming
for Ruby in-depth, the main feature of which is method wrapping (known as
advice in AOP terms). Currently method wrapping is generally approached via
method aliasing, but a better way comes from the realization that subclassing
already entails method wrapping. All that is needed is a way to annonymously
subclass
.

class A < A

is one way to to do this, but requires moving method definitions into the
super class when they are subsequently defined. It is not a perfect solution,
and was merely used in one possible test implementation.

That’s a highly concise explination. If you are interested in this,
understanding more about it, or other related topics, please join the
suby-muse mailing list. It’s a reasonably low traffic list, so no worries of
being bombarded with emails.

http://lists.berlios.de/mailman/listinfo/suby-muse

Currently, the discussion has led us into considerations of Multiple
Inheritence. It is interesting to note that Ruby is actually but a hair’s
breath from being a type of MI language.

One last note: class A < A can be useful in and of itself for similar reasons.
If for instance, one wished to redefine a class as an elaboration on the
current class, as opposed to altering the class directly aliasing numerous
methods.

···

On Tuesday 23 December 2003 09:51 am, Ian Hobson wrote:

This still does not answer the question of why? (At least for me), so
I’m jumping in here are asking it again!

When you can simply extend class A with any new method you need, why do
you want to create a subclass and pretend it is the class you started
with?


T.