這段代碼創建方法作爲私有方法,爲什麼?爲什麼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
這段代碼創建方法作爲私有方法,爲什麼?爲什麼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
方法測試(所謂全局方法)實際上定義爲Object
私有實例方法。這樣,可以隨處調用(因爲一切都從Object
繼承),並且只能在沒有明確接收者的情況下調用它們。
這包括像require
,load
,puts
,print
,p
,gets
,和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
只是Class
(class
的任何類是總是Class
),所以如果做工作像您期望的,該方法將在Class
定義,而不是在A
。
我在Ruby 1.9.3中沒有這個問題。它按照你的預期工作。 – tadman
@tadman,我更新了我的問題 – megas
我不確定你是如何得到這個錯誤的。 'eval'以某種方式補丁到別的東西? – tadman