Ruby - метод определения происхождения? - PullRequest
27 голосов
/ 16 августа 2010

При отправке сообщения объект Ruby ищет, есть ли у него метод с таким именем для ответа. Его поиск метода выполняет поиск в следующем порядке и использует первый найденный метод.

  1. Синглтон-методы, определенные для себя (также известные как «собственный класс»)
  2. Методы, определенные в его классе
  3. Любые модули, смешанные с его классом, в обратном порядке включения (только самое раннее включение данного модуля имеет какой-либо эффект - если суперкласс включает модуль A, а подкласс включает его снова, он игнорируется в подклассе; если подкласс включает в себя A, затем B, затем A, второй A игнорируется) ( update : обратите внимание, что это было написано до того, как Module.prepend существовало)
  4. Его родительский класс
  5. Любые методы, смешанные с родительским классом, родительским родителем и т. Д.

Или, проще говоря, он выглядит сам по себе, затем все в self.class.ancestors в том порядке, в котором они перечислены.

Этот путь поиска следует в момент вызова метода; если вы создаете экземпляр класса, затем заново открываете класс и добавляете метод или смешиваете его через модуль, существующий экземпляр получит доступ к этому методу.

Если все это не удается, он проверяет, есть ли у него метод method_missing или его класс, его родительский класс и т. Д.

У меня такой вопрос: кроме проверки кода вручную или использования примеров методов, таких как puts "I'm on module A!", вы можете сказать, откуда появился данный метод? Можете ли вы, например, перечислить объект методы и увидеть: «Этот класс находится в родительском классе, этот модуль - в модуле A, этот класс - в классе и переопределяет родительский класс» и т. д.?

Ответы [ 4 ]

25 голосов
/ 16 августа 2010

Object#method возвращает объект Method, дающий метаданные о данном методе.Например:

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

В Ruby 1.8.7 и более поздних версиях вы можете использовать Method#owner для определения класса или модуля, который определил метод.

Комуполучить список всех методов с именем класса или модуля, в котором они определены, вы можете сделать что-то вроде следующего:

obj.methods.collect {|m| "#{m} defined by #{obj.method(m).owner}"}
9 голосов
/ 16 августа 2010

Получите соответствующий объект Method (или UnboundMethod) и запросите его owner.Таким образом, вы могли бы сделать method(:puts).owner и получить Kernel.

6 голосов
/ 16 августа 2010

Чтобы найти, какие методы экземпляра определены в A (но не в суперклассах):

A.methods(false)

Чтобы найти, какие методы экземпляра определены в A И его суперклассах:

A.methods

Чтобы определить, для какого класса (или модуля) данный метод определен:

method(:my_method).owner

Чтобы определить, какой объект является получателем для данного метода:

method(:my_method).receiver
1 голос
/ 16 августа 2010

Вы можете использовать Object#method. Например,

[1, 2, 3].method(:each_cons) # => #<Method: Array(Enumerable)#each_cons>

сообщает, что метод each_cons массива происходит из модуля Enumerable.

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