2013-08-04 1 views
5

Я знаю, что send принимает строку или символ с аргументами, в то время как instance_eval принимает строку или блок, и их различие может быть очевидным с учетом получателей.Разница в Ruby между send и instance_eval?

Мой вопрос: «под капотом» разница для примера ниже?

1234.send 'to_s'    # '1234' 
1234.instance_eval 'to_s'  # '1234' 

ответ

7

От fine manual:

посыла (символ [, арг ...]) → OBJ
посыла (строка [, арг ...]) → OBJ

Вызывает метод, идентифицированный символом, передавая ему любые указанные аргументы. [...] Когда метод идентифицируется строкой, строка преобразуется в символ.

и instance_eval:

instance_eval (строка [, имя файла [, LINENO]]) → OBJ
instance_eval {| | Блок} → OBJ

Оценивает строку, содержащую Ruby, исходный код, или данный блок, в контексте приемника (OBJ). Чтобы установить контекст, переменная self установлена ​​в obj во время выполнения кода, предоставляя коду доступ к переменным экземпляра obj.

Так send выполняет метод, тогда как instance_eval выполняет произвольный блок кода (в виде строки или блока) с self набором к объекту, который вы звоните instance_eval дальше.

В вашем случае нет большой разницы, поскольку строка, которую вы передаете instance_eval, - это всего лишь один метод. Главное отличие заключается в том, что любой, кто читает ваш код (включая вас через шесть месяцев), будет задаваться вопросом, почему вы используете instance_eval для вызова одного метода.

Вы также можете быть заинтересованы в Object#public_send и BasicObject#__send__

+1

Отлично, я уже задаюсь вопросом, почему у меня был единственный метод для 'instance_eval'. –

5

Все, что вы можете сделать с send является подмножеством, что из instance_eval. А именно, аргумент send должен быть единственным методом (и его аргументами), тогда как аргумент instance_method является произвольным кодом. Поэтому всякий раз, когда у вас есть send, вы можете переписать его с помощью instance_eval, но не наоборот.

Однако, производительность повышается, send гораздо быстрее, чем instance_eval, так как нет никакого дополнительного разбора требуется выполнить send, в то время как instance_eval потребности разобрать весь аргумент.

В вашем примере результат будет таким же, но первый будет работать быстрее.

+1

Хорошее резюме, и я получил бонус о производительности! –

 Смежные вопросы

  • Нет связанных вопросов^_^