2012-09-19 51 views
2

這段代碼創建方法作爲私有方法,爲什麼?爲什麼eval將方法創建爲私有方法?

a = %q{def hello() "Hello there!" end} 
class A; end 
A.class.send(:eval, a) 
A.new.hello #=> NoMethodError: private method `hello' called for A 

平臺:紅寶石1.9.3p125,在其中任何模塊之外定義pry

+0

我在Ruby 1.9.3中沒有這個問題。它按照你的預期工作。 – tadman

+0

@tadman,我更新了我的問題 – megas

+0

我不確定你是如何得到這個錯誤的。 'eval'以某種方式補丁到別的東西? – tadman

回答

5

方法測試(所謂全局方法)實際上定義爲Object私有實例方法。這樣,可以隨處調用(因爲一切都從Object繼承),並且只能在沒有明確接收者的情況下調用它們。

這包括像requireloadputsprintpgets,和eval方法。 (注:其中大部分是實際上Kernel定義並混入Object但效果和目標是一致的。)

在你的情況,你定義任何模塊之外的方法:有在您的a字符串中沒有提及模塊。您在A.class上撥打eval的事實完全不相關。就像我上面說過的那樣:eval是一個全局方法,由於方便的原因在Object上定義(這樣可以在任何地方調用它)。你的A.class.send(:eval)只是一個非常複雜的方式調用全球私人eval方法。它不會奇蹟般地將eval的字符串的上下文設置爲A.class

你可以做42.send(:eval)代替,結果仍然是一樣的,就像puts('Hello')42.send(:puts, 'Hello')是完全一樣的,因爲他們最終調用完全相同的方法。

並順便說一句:即使它確實,它仍然不會做你想要的。 A.class只是Classclass的任何類是總是Class),所以如果工作像您期望的,該方法將在Class定義,而不是在A

相關問題