2015-11-22 4 views
1

Я изучаю метапрограммирование ruby ​​в данный момент, и пока я играл и тестировал материал, я наткнулся на то, на что я не могу найти ответ. Допустим, мы имеем следующий код:Ruby: разница между def и define_method

class Foo 
end 
Foo.instance_eval do 
    define_method("bar") do 
    1 
    end 
end 

Я хотел бы ожидать, чтобы добавить метод класса под названием bar к Foo, но вместо того, чтобы, когда я вызываю метод он говорит, что это не определено. Что еще меня озадачивает, так это то, что тот же код работает, когда я использую def вместо define_method. Оба способа работают, когда я пытаюсь определить метод экземпляра с class_eval. Так что же здесь происходит?

Заранее спасибо.

+7

Возможный дубликат [Ruby: определить \ _method против . def] (http://stackoverflow.com/questions/185947/ruby-define-method-vs-def) – Sean

+0

Я прочитал этот пост, прежде чем публиковать мои, и я этого не понимал. – Robert

+0

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

ответ

1

Давайте сделаем это простым.

define_method - это способ. Или я должен сказать метод частного класса класса Object. Вы вызываете его, указывая ему аргумент как имя метода экземпляра, которое вы собираетесь определить, и блок, который содержит код метода. apidock имеет очень четкое определение. Возможно, вы захотите прочитать документацию.

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

Если вы пытаетесь определить метод класса, используйте class_eval и дайте ему строку. Как видно из названия, instance_eval определяет материал на уровне экземпляра. В вашем коде, если вы делаете Foo.instance_methods, вы найдете метод bar. Так что если вы делаете Foo.new.bar, он возвращает 1, так как TK-421 ответил вам. Но так как define_method определяет instance_method, как указано в документации, независимо от того, используете ли вы class_eval или instance_eval, вы получите метод экземпляра.

Вот документация, которую вы можете прочитать, и они ответят на все ваши вопросы.

class_eval: http://apidock.com/ruby/v1_9_3_392/Module/class_eval

define_method: http://apidock.com/ruby/Module/define_method

instance_eval: http://apidock.com/ruby/Object/instance_eval

И не забывайте, это все могучее: http://www.google.com: D

+0

Большое спасибо, полное и ясное объяснение действительно :) – Robert

0

Это метод экземпляра. Таким образом:

f = Foo.new 
f.bar # 1 
+5

Насколько я понимаю, это не отвечает на вопрос 'def' vs' define_method'. – Sean

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