如何确定指定方法的起源类?

时间:2009-01-22 03:30:33

标签: ruby

我从this discussion得到了这个问题。类似object.m的方法调用并不总是意味着“object”类具有“m”方法,就像Array对象的find方法不是直接源自Array对象,而是来自混合的Enumerable模块。我的问题是,给定一种方法,我们如何确定方法起源的类?

5 个答案:

答案 0 :(得分:10)

任何类/对象方法都是Ruby中的一个对象,并且有一些自己的方法。

所以你可以这样做:

[].method(:count).inspect
=> "#<Method: Array#count>"

[].method(:detect).inspect
=> "#<Method: Array(Enumerable)#detect>"

RegEx的快点,你已经完成了。

答案 1 :(得分:7)

tobyhede的答案很棒,但我只是在irb中进行了一些挖掘,并且没有必要将#inspect的输出切片。 Method

>> Object.new.method(:inspect)
=> #<Method: Object(Kernel)#inspect>

有一些有用的方法:

>> Object.new.method(:inspect).methods - Object.methods
=> ["owner", "call", "to_proc", "unbind", "arity", "receiver", "[]"]

特别是#owner方法,它将所有者作为正确的对象返回:

>> [].method(:count).owner
=> Array
>> [].method(:detect).owner
=> Enumerable

答案 2 :(得分:1)

也许你使用caller()给你回溯看看:

http://www.ruby-doc.org/core/classes/Kernel.html#M005955

答案 3 :(得分:1)

我认为这样的事情可以发挥作用

def print_ancestor_definitions(cl,method)
  ancestors = cl.ancestors
  p ancestors.join(' < ') #Print heirarchy
  p "Searching..."
  ancestors.each do |c|
    if c.instance_methods.include? method
      p "#{c} defines #{method} as an instance method!"
    elsif c.singleton_methods.include? method
      p "#{c} defines #{method} as a singleton method"
    else
      p "#{c} doesn't define #{method}"
    end
  end
end

print_ancestor_definitions(Array,'find')
# >> "Array < Enumerable < Object < Kernel"
# >> "Searching..."
# >> "Array defines find as an instance method!"
# >> "Enumerable defines find as an instance method!"
# >> "Object doesn't define find"
# >> "Kernel doesn't define find"

我想最后一个拥有该方法的人是定义它的人吗?

答案 4 :(得分:0)

我不确定我们是否可以精确地找到方法的来源,当你包含一个mixin时,所有方法都会成为你班级的一部分,就像你把它们放在那里一样。请参阅dylanfm的答案约。