Mommy, where do methods come from?

(Sorry for the subject; couldn’t help myself! :slight_smile:

My (quite serious) question:

Is there a way to tell in which module an object’s method was defined?

For example:

class Foo
def to_s; ‘foo’; end
end

class Bar; end

foo = Foo.new
bar = Bar.new

foo.methodClass :to_s # Hopefully returns Foo.
bar.methodClass :to_s # Hopefully returns Object.

Furthermore, is there a way to tell all of the modules which did define a
method for a given object?

foo.methodClasses :to_s # Hopefully returns [Foo, Object].

Finally (and I’m sure I should know this one already), how would I call
Object#to_s on foo if I have already redefined to_s? (Is this even
possible?)

Many thanks,

Chris

Hi,

Is there a way to tell in which module an object’s method was defined?

For example:

class Foo
def to_s; ‘foo’; end
end

class Bar; end

foo = Foo.new
bar = Bar.new

module Kernel
  def methodClass(m)
    m = "#{m}"
    self.class.ancestors.find {|c| c.instance_methods.include?(m)}
  end
end

foo.methodClass :to_s # Hopefully returns Foo.
bar.methodClass :to_s # Hopefully returns Object.

But bar.to_s is defined in Kernel.

Once method of Method returns original class was proposed, but
wasn’t accepted because of its name.

Furthermore, is there a way to tell all of the modules which did define a
method for a given object?

foo.methodClasses :to_s # Hopefully returns [Foo, Object].

Replace find with find_all in above.

Finally (and I’m sure I should know this one already), how would I call
Object#to_s on foo if I have already redefined to_s? (Is this even
possible?)

Impossible outside redefined to_s, unless it’s aliased.

···

At Thu, 19 Dec 2002 03:05:20 +0900, Chris Pine wrote:


Nobu Nakada

Hi –

(Sorry for the subject; couldn’t help myself! :slight_smile:

My (quite serious) question:

Is there a way to tell in which module an object’s method was defined?

For example:

class Foo
def to_s; ‘foo’; end
end

class Bar; end

foo = Foo.new
bar = Bar.new

foo.methodClass :to_s # Hopefully returns Foo.
bar.methodClass :to_s # Hopefully returns Object.

Furthermore, is there a way to tell all of the modules which did define a
method for a given object?

foo.methodClasses :to_s # Hopefully returns [Foo, Object].

class Object
def mc(meth,mess)
self.class.ancestors.send(mess) {|mod|
mod.instance_methods.include?(meth.to_s)
}
end

def method_class(meth)
  mc(meth,:detect)
end

def method_classes(meth)
  mc(meth,:select)
end

end

p “”.method_class(“to_s”) # String
p Object.new.method_class(“to_s”) # Kernel
p “”.method_classes(“to_s”) # [String, Kernel]

class Foo
def to_s; end
end

foo = Foo.new
p foo.method_classes(“to_s”) # [Foo, Kernel]

David

···

On Thu, 19 Dec 2002, Chris Pine wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Finally (and I’m sure I should know this one already), how would I call
Object#to_s on foo if I have already redefined to_s? (Is this even
possible?)

class Base
def foo
15
end
end

Now we want to access Base#foo in derived even though it’s overwritten.

class Derived
alias_method :old_foo, :foo

def foo
-72
end

def bar
old_foo
end
end

I don’t think it’s a very nice way to do it, but then I’ve never needed to.

Gavin

···

From: “Chris Pine” nemo@hellotree.com

module Kernel
  def methodClass(m)
    m = "#{m}"
    self.class.ancestors.find {|c| c.instance_methods.include?(m)}
  end
end

Here is a slightly extended version which (hopefully) allows
for ``undef’s" and/or singletons methods.

···

nobu.nokada@softhome.net wrote


module Kernel
def methodClass(m)
m = m.to_s
# catch method undef’s
respond_to?(m) or return nil
# meta class is first inline
extended_anc = self.class.ancestors.unshift(class << self; self end)
extended_anc.find {|c| c.instance_methods.include?(m) }
end
end

/Christoph

Hi,

Once method of Method returns original class was proposed, but
wasn’t accepted because of its name.

An alternative.

module Kernel
def methodClass(m)
/: (\S+?)(?:((\S+)))?#/ =~ method(m).inspect
eval($2 || $1)
end
end

···

At Thu, 19 Dec 2002 03:50:23 +0900, nobu.nokada@softhome.net wrote:


Nobu Nakada

Hello nobu,

Wednesday, December 18, 2002, 9:50:23 PM, you wrote:

Finally (and I’m sure I should know this one already), how would I call
Object#to_s on foo if I have already redefined to_s? (Is this even
possible?)

Impossible outside redefined to_s, unless it’s aliased.

if Ruby will call some method before adding each method, it will be possible

···


Best regards,
Bulat mailto:bulatz@integ.ru

Christoph wrote:

module Kernel
def methodClass(m)
m = m.to_s
# catch method undef’s
respond_to?(m) or return nil
# meta class is first inline
extended_anc = self.class.ancestors.unshift(class << self; self end)
extended_anc.find {|c| c.instance_methods.include?(m) }
end
end

Hm. Since #respond_to? is doing this work alread, maybe it would make
sense for it to return the Module where it finds a method, instead of
just true?

Sorta like how defined?(arg) returns not just a boolean value but the
kind of thing arg is.

Hi,

···

At Thu, 19 Dec 2002 14:41:28 +0900, Bulat Ziganshin wrote:

Finally (and I’m sure I should know this one already), how would I call
Object#to_s on foo if I have already redefined to_s? (Is this even
possible?)

Impossible outside redefined to_s, unless it’s aliased.

if Ruby will call some method before adding each method, it will be possible

Unfortunately, such hooks are only Class#method_added and so
on, which will be called after it.


Nobu Nakada

Hm. Since #respond_to? is doing this work alread, maybe it would make
sense for it to return the Module where it finds a method, instead of
just true?

Sorta like how defined?(arg) returns not just a boolean value but the
kind of thing arg is.

Sounds like a very good idea to me …

/Christoph

···

“Joel VanderWerf” vjoel@PATH.Berkeley.EDU wrote

Hi,

Christoph wrote:

module Kernel
def methodClass(m)
m = m.to_s
# catch method undef’s
respond_to?(m) or return nil
# meta class is first inline
extended_anc = self.class.ancestors.unshift(class << self; self end)
extended_anc.find {|c| c.instance_methods.include?(m) }
end
end

Hm. Since #respond_to? is doing this work alread, maybe it would make
sense for it to return the Module where it finds a method, instead of
just true?

Maybe nice.

Sorta like how defined?(arg) returns not just a boolean value but the
kind of thing arg is.

defined?(arg) returns a string represents type of arg or nil,
not true/false.

···

At Thu, 19 Dec 2002 07:41:14 +0900, Joel VanderWerf wrote:


Nobu Nakada

Hello nobu,

Thursday, December 19, 2002, 9:21:52 AM, you wrote:

Finally (and I’m sure I should know this one already), how would I call
Object#to_s on foo if I have already redefined to_s? (Is this even
possible?)

Impossible outside redefined to_s, unless it’s aliased.

if Ruby will call some method before adding each method, it will be possible

Unfortunately, such hooks are only Class#method_added and so
on, which will be called after it.

class Class
def method_added
puts “sorry, it’s too late to save prevous method definition”
puts “… but i can save the current definition for future references”
puts “… are you sure you are absolutely need to do IT?”
if gets==“y”
$secret_hash[class][method] << method_definition
end
end
end

classes.each { |class|
class.methods.each { |method|
$secret_hash[class][method] << method_definition
}
}

···


Best regards,
Bulat mailto:bulatz@integ.ru