2015-05-30 59 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) 

看來,在方法test1test2i值沒有定義期間取代,而是直接計算在現場,當方法被調用。所以我們只看到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 

基本上是由什麼奧雅納鏈接的問題是關於

+0

這完全回答了這個問題,謝謝! – overdawn