How to find out a method's defining class?

Hi,

1. a method created with Classname.method( 'method_name' )
knows the class it's defined for, as inspect shows.

Object.methods returns an Array of Strings only.

ObjectSpace.each_object( Method ) delivers methods created
as in 1. only

Does Reflection provides a way to find out ?

Thanks in advance
rg

i don't know a direct way, but maybe:

   harp:~ > cat a.rb
   class Object
     def defines method
       singleton_class = class << self; self; end
       ([singleton_class] + self.class.ancestors).reverse.each do |a|
         return a if a.instance_methods.include? method
       end
       return nil
     end
     alias defines? defines
   end

   module M
     def foobar; end
   end
   class C
     def foo; end
   end
   class B < C
     include M
     def bar; end
   end

   obj = B::new
   p(obj.defines('foo'))
   p(obj.defines('bar'))
   p(obj.defines('foobar'))

   a =
   class << a
     def singleton_method; end
   end
   p(a.defines('each'))
   p(a.defines('singleton_method'))
   p(a.defines('not_defined'))

   harp:~ > ruby a.rb
   C
   B
   M
   Array
   #<Class:#<Array:0xb75d1db4>>
   nil

note that this is just an idea - but it may suit your purposes.

hth.

-a

···

On Tue, 19 Jul 2005, Rolf Gebauer wrote:

Hi,

1. a method created with Classname.method( 'method_name' )
knows the class it's defined for, as inspect shows.

Object.methods returns an Array of Strings only.

ObjectSpace.each_object( Method ) delivers methods created
as in 1. only

Does Reflection provides a way to find out ?

Thanks in advance

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
My religion is very simple. My religion is kindness.
--Tenzin Gyatso

===============================================================================

Rolf Gebauer wrote:

Hi,

1. a method created with Classname.method( 'method_name' )
knows the class it's defined for, as inspect shows.

Object.methods returns an Array of Strings only.

ObjectSpace.each_object( Method ) delivers methods created
as in 1. only

Does Reflection provides a way to find out ?

Like Ara said, it doesn't seem to be provided :frowning:
So, another (crude) hack ...

···

#---------------------------------
class Method
   def definer_class
     inspect =~ /:\s(\w+)/
     Object.const_get($1)
   end
end
#---------------------------------
tm = Time.method(:now)
p tm #-> #<Method: Time.now>
p tm.definer_class #-> Time
#---------------------------------

<aside:>
Internally the information we want is stored in an
instance_variable called @__attached__ but it's not
accessible from a script. (??)

p tm.instance_variable_get(:@__attached__)
p tm.class.instance_variable_get(:@__attached__)
p (class << tm; self; end).instance_variable_get(:@__attached__)
#-> nil # (all)
</aside:>

daz

Ara.T.Howard <Ara.T.Howard <at> noaa.gov> writes:

i don't know a direct way, but maybe:

   harp:~ > cat a.rb
   class Object
     def defines method
       singleton_class = class << self; self; end
       ([singleton_class] + self.class.ancestors).reverse.each do |a|
         return a if a.instance_methods.include? method
       end
       return nil
     end
     alias defines? defines
   end

If you want to get at the class reported by Method#inspect, you shouldn't
reverse the ancestors list. As a consequence, you have to treat singleton
methods special. If you also want to support private singleton methods, it gets
really nasty. If someone needs this (support for private singleton methods), I
can show you the code.

Regards,
Pit