Как определить класс, из которого происходит указанный метод? - PullRequest
7 голосов
/ 22 января 2009

Я получил этот вопрос от этого обсуждения . Вызов метода, подобный object.m, не всегда означает, что класс «object» имеет метод «m», точно так же, как метод find для объекта Array напрямую не создается из объекта Array, а из смешанного модуля Enumerable. Мой вопрос, учитывая метод, как мы можем определить класс, из которого произошел метод?

Ответы [ 5 ]

10 голосов
/ 22 января 2009

Любой метод класса / объекта является объектом в Ruby и имеет несколько собственных методов.

Так что вы можете сделать это:

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

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

Быстрый бит RegEx, и все готово.

7 голосов
/ 01 февраля 2009
Ответ

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
1 голос
/ 22 января 2009

Я думаю, что-то подобное может сработать

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"

Полагаю, последним, у кого есть метод, является тот, кто его определяет?

1 голос
/ 22 января 2009

может быть, вы используете функцию caller (), чтобы получить обратную трассировку:

http://www.ruby -doc.org / ядро ​​/ классов / Kernel.html # M005955

0 голосов
/ 22 января 2009

Я не уверен, что мы можем точно определить, откуда появился метод, когда вы добавляете миксин, все методы становятся частью вашего класса, как если бы вы их туда поместили. См. Ответ от dylanfm для приблиз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...