Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieving the Method instance from within a method in Ruby

This is a follow-up question to How to determine the class a method was defined in? (hope you don't mind the similarity)

Given a class hierarchy, can a method retrieve its own Method instance?

class A
  def foo
    puts "A#foo: `I am #{method(__method__)}'"
  end
end

class B < A
  def foo
    puts "B#foo: `I am #{method(__method__)}'"
    super
  end
end

A.new.foo
# A#foo: `I am #<Method: A#foo>'

B.new.foo
# B#foo: `I am #<Method: B#foo>'
# A#foo: `I am #<Method: B#foo>' # <- A#foo retrieves B#foo

So that B.new.foo instead prints

# B#foo: `I am #<Method: B#foo>'
# A#foo: `I am #<Method: A#foo>' # <- this is what I want

In the previous question, Jörg W Mittag suspected that retrieving the class a method was defined in might violate object-oriented paradigms. Does this apply here, too?

Shouldn't a method "know itself"?

like image 651
Stefan Avatar asked Dec 03 '25 07:12

Stefan


2 Answers

I found a method that exactly does that.

class A
  def foo
    puts "A#foo: `I am #{method(__method__).super_method || method(__method__)}'"
  end
end

I really admire Matz and the Ruby core developers. The existence of such method means that they had in mind such situation, and had thought about what to do with it.

like image 112
sawa Avatar answered Dec 04 '25 22:12

sawa


Building on answer of How to determine the class a method was defined in? and @sawa's answer with respect to super_method, you can use:

def meth(m, clazz)
    while (m && m.owner != clazz) do 
        m = m.super_method
    end
    return m
end

class A 
  def foo
    puts "A#foo: `I am #{meth(method(__method__), Module.nesting.first)}'"
  end
end

class B < A
  def foo
    puts "B#foo: `I am #{meth(method(__method__), Module.nesting.first)}'"
    super
  end
end


B.new.foo
# B#foo: `I am #<Method: B#foo>'
# A#foo: `I am #<Method: A#foo>'

Idea here is that since we know the class/module where the method is defined by Module.nesting.first, we take the current method object found by method(__method__) and iterate through its super chain to find that instance of method whose owner is same as the class/module that defined the method.

like image 25
Wand Maker Avatar answered Dec 05 '25 00:12

Wand Maker



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!