method_missing в "Программировании Ruby" над моей головой - PullRequest
2 голосов
/ 04 апреля 2009

method_missing

* obj.method_missing (символ h, args i) → other_obj

Вызывается Ruby при отправке obj сообщение, которое он не может обработать. символ символ для вызываемого метода, и аргументы любые аргументы, которые были перешел на это. Пример ниже создает класс Roman, который отвечает к методам с именами, состоящими из римские цифры, возвращающие соответствующие целочисленные значения. Еще Типичное использование метода method_missing заключается в реализовать прокси, делегаты и экспедиторы.

class Roman
  def roman_to_int(str)
    # ...
  end
  def method_missing(method_id)
    str = method_id.id2name
    roman_to_int(str)
  end
end
r = Roman.new
r.iv ! 4
r.xxiii ! 23
r.mm ! 2000

Я только что услышал о пропущенном методе и пошел, чтобы узнать больше в Программирование на Ruby , но приведенное выше объяснение, приведенное в книге, у меня над головой. У кого-нибудь есть более простое объяснение? Точнее говоря, метод отсутствия данных используется только интерпретатором или когда-либо возникает необходимость вызывать его напрямую в программе (при условии, что я просто пишу веб-приложения, а не пишу код для НАСА)?

Ответы [ 7 ]

12 голосов
/ 04 апреля 2009

Вероятно, лучше не думать о рубине как о методе. Когда вы вызываете метод ruby, вы фактически отправляете сообщение этому экземпляру (или классу), и если вы определили обработчик для сообщения, оно используется для обработки и возврата значения.

Так что method_missing - это специальное определение, которое вызывается всякий раз, когда ruby ​​не может найти подходящего обработчика. Вы также можете думать об этом как о * методе.

5 голосов
/ 04 апреля 2009

В Ruby нет принудительного применения типов, а также не выполняется проверка того, какие методы используются у объекта при первом синтаксическом анализе сценария, поскольку это может быть динамически изменено при запуске приложения.

То, что делает method_missing, позволяет вам перехватывать и обрабатывать вызовы методов, которые не существуют для данного объекта. Это обеспечивает скрытую мощь практически каждого DSL (предметно-ориентированного языка), написанного на Ruby.

В этом примере каждый из 'r.iv', 'r.mm' и т. Д. На самом деле является вызовом метода для римского объекта. Конечно, у него нет метода 'iv' или 'mm', поэтому вместо этого передается управление методу method_missing, который получает имя вызванного метода, а также любые переданные аргументы.

method_missing затем преобразует имя метода из символа в строку и анализирует его как римское число, возвращая результат в виде целого числа.

5 голосов
/ 04 апреля 2009

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

SomeModel.find_by_name_and_number(a_name, a_number)

Модель не содержит код для этого find_by, поэтому вызывается метод method_missing, который смотрит, говорит: я распознаю этот формат и выполняю его. Если этого не произойдет, вы получите ошибку метода not found.

3 голосов
/ 04 апреля 2009

В предоставленном вами римском примере показано, как можно расширить функциональность класса без явного определения методов.

r.iv не является методом, поэтому method_missing перехватывает его и вызывает roman_to_int для идентификатора метода "iv"

Это также полезно, когда вы хотите обрабатывать нераспознанные методы в других местах, такие как прокси, делегаты и пересылки, как указано в документации.

2 голосов
/ 04 апреля 2009

Вы не звоните "method_missing" (переводчик называет это). Скорее, вы определяете его (переопределяете) для класса, который вы хотите сделать более гибким. Как упоминалось в других комментариях, интерпретатор будет вызывать вашу версию method_missing, когда класс (или экземпляр) не («явно»?) Определяет запрошенный метод. Это дает вам возможность что-то придумать, основываясь на методе / имени сообщения ersatz.

Вы когда-нибудь занимались программированием "рефлексии" на Java? Использование этого метода было бы таким, как если бы класс, к которому осуществляется доступ через отражение, мог бы посмотреть на строку (извините, «символ») имени метода, если было сгенерировано исключение no-such-method, и затем создать что-то, как этот метод реализация на лету.

Динамическое программирование - это своего рода «односторонний подход» в рефлексии.

1 голос
/ 16 августа 2011

ActiveRecord использует method_missing для определения методов find_by. Но так как method_missing в основном является последним средством, это может стать серьезным узким местом производительности. Я обнаружил, что ActiveRecord делает еще одно потрясающее метапрограммирование, определяя новый метод поиска как метод класса !! Таким образом, любые дальнейшие вызовы того же метода поиска не будут попадать в method_missing, потому что теперь это метод класса. Для получения подробной информации о текущем фрагменте кода из base.rb нажмите здесь .

1 голос
/ 04 апреля 2009

Поскольку вы упоминаете веб-приложения, я думаю, что вы знакомы с Ruby on Rails. Хорошим примером того, как можно использовать method_missing, являются различные доступные методы find_by_<whatever>. Ни один из этих методов на самом деле не существует! Они синтезируются во время выполнения. Вся эта магия происходит из-за того, что ruby ​​перехватывает вызовы несуществующих методов.

Вы можете узнать больше об этом и других применениях method_missing здесь .

...