2015-05-30 2 views
4

Я хотел бы понять, как работает define_method и как правильно использовать переменные за пределами блока определения. Вот мой код:Использование локальных переменных в define_method

class Test 
    def self.plugin 
    for i in 1..2 
     define_method("test#{i}".to_sym) do 
     p i 
     end 
    end 
    end 
    plugin 
end 

ob = Test.new 
ob.test1 #=> 2 (I would expect 1) 
ob.test2 #=> 2 (I would expect 2) 

кажется, что в методах test1 и test2, значение i не замещается во время определения, но вычисляется непосредственно на месте, когда вызывается метод. Таким образом, мы видим только последнее значение i, которое составляет 2. Но откуда Ruby берет это значение? И есть ли способ дать test#{i} печать i?

В этом конкретном случае я мог бы сделать workaround using __method__, но, вероятно, есть лучшее решение.

+0

сила _closure_ выражается здесь .......... :) Спасибо за –

+0

ссылка, вопрос касается той же проблемы. Но я не уверен, что там предоставлено решение. По крайней мере, один из комментариев не работает:

class Test for name in [ :new, :create, :destroy ] local_name = name define_method("test_#{local_name}") do puts local_name end end end ob = Test.new ob.test_new #=> destroy (I would expect 'new') ob.test_create #=> destroy (I would expect 'new') 
overdawn

+0

Ну .. Без маркировки. Но здесь [аналогичный пост] (http://stackoverflow.com/questions/2029524/how-are-variables-bound-to-the-body-of-a-define-method). –

ответ

5

Как упоминалось в комментариях, это сводится к закрытию - блок, переданный в define_method, фиксирует локальные переменные из его объема (а не только их значение, как вы выяснили).

for не создает новую область действия, поэтому ваш метод «видит» изменение на i. Если вы используете блок (например, с каждым), то создается новая область, и этого не произойдет. Вам просто нужно изменить свой код

class Test 
    def self.plugin 
    (1..2).each do |i| 
     define_method("test#{i}".to_sym) do 
     p i 
     end 
    end 
    end 
    plugin 
end 

который является в основном то, что вопрос связан по Arup был о

+0

Это полностью отвечает на вопрос, спасибо! – overdawn

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