2011-02-26 23 views
4

我一直試圖在Ruby 1.9中動態地定義一些實例方法。這是我一直在使用嘗試了這一點代碼:內核#__ method__在動態定義的方法中似乎不能正確工作

class Testing 
    [:one, :two].each do |name| 
    define_method(name) do 
     puts __method__ 
    end 
    end 
end 

而這裏的輸出:

ruby-1.9.2-p180 :008 > t = Testing.new 
=> #<Testing:0x00000100961878> 
ruby-1.9.2-p180 :009 > t.one 
two 
=> nil 
ruby-1.9.2-p180 :010 > t.two 
two 
=> nil 
ruby-1.9.2-p180 :011 > 

我希望的結果是onetwo分別。如果我在調用迭代之外調用define_method,它會按預期工作。我在這裏不瞭解什麼?

這是我在網上看到的迭代中調用的define_method的許多例子之一。 Dynamically defined setter methods using define_method?

什麼是缺失?

此外:使用__method__對我來說並不重要,但它是我能夠顯示的最好方式,看起來好像只有發送到define_method的最後一個塊被用於定義的方法。也許這是開始解釋這個問題給我,但我還是不明白..

+0

我試過你的代碼,它在這裏工作完美,'t.one'打印_「一個」_。 – 2011-02-26 21:21:13

+0

它可能是我的紅寶石版本中的錯誤? *編輯:爲記錄,這是否工作在Ruby 1.8 – Iamvery 2011-02-26 22:31:07

+0

此處確認的行爲(1.9.2),t.one打印「two」。聞起來像一個錯誤。 – steenslag 2011-02-26 23:11:12

回答

3

尼斯發現奇怪的行爲。在我測試的所有紅寶石中,只有MRI 1.9.2證明了這一點。

Ryan Davis有reported the bug on the ruby-core list(引用此問題)。

+0

JRuby 1.7也顯示此行爲:http://stackoverflow.com/questions/26966547/is-jrubys-implementation-of-kernel-method-broken/26968484#26968484 – 2014-11-18 03:13:40

0

您可以使用這樣的事情,而不是define_method

class Testing 
    [:one, :two].each do |name| 
    eval <<-EOM 
     def #{name} 
      puts __method__ 
     end 
    EOM 
    end 
end 

t = Testing.new 
t.one #=> "one" 
t.two #=> "two" 
+0

當然有比這更清潔的方法嗎? – Iamvery 2011-02-26 22:31:39

0

出現這種情況的原因是,define_method定義方法與def有些不同。它與創建匿名特效和lambda表達式有關。我想建議的是簡單地使用方法名稱,因爲你已經擁有了它。這應該避免搜索的方法名稱的堆棧跟蹤爲好,所以應該有更好的表現:

class Testing 
    [:one, :two].each do |name| 
    define_method name do 
     "This method's name is #{name}." 
    end 
    end 
end 

Testing.new.one 
=> This method's name is one. 
Testing.new.two 
=> This method's name is two. 

爲了澄清,注意什麼是由以下兩個語句返回:

class Testing 
    define_method :one do 
    __method__ 
    end 
end 
=> #<Proc:[email protected](irb):54 (lambda)> 

class Testing 
    def one 
    __method__ 
    end 
end 
=> nil 

PS :使用這兩種格式之間也存在性能差異。您可以使用Benchmark驗證自己def是否比define_method快。

+0

你的回答是一個很好的「在行間讀取並找出真正意圖是什麼」的答案,但它似乎仍然像'Kernel #__ method__'在MRI 1.9.2中有一個錯誤。 – 2011-02-27 03:17:14

+0

是的,很可能,但我可以看到它被證明是實施方法的區別。匿名proc/lambda沒有方法名稱,至少可以解釋一些奇怪的行爲。 – 2011-02-27 06:54:37

相關問題