这段代码将方法创建为私有方法,为什么?
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
平台:ruby 1.9.3p125,在pry
答案 0 :(得分:5)
在任何模块之外定义的方法(所谓的全局方法)实际上被定义为Object
的私有实例方法。这样,可以随处调用(因为所有内容都来自Object
),并且只能在没有显式接收器的情况下调用它们。
这包括require
,load
,puts
,print
,p
,gets
和eval
等方法。 (注意:其中大多数实际在Kernel
中定义并混合到Object
但效果和目标是相同的。)
在您的情况下, 定义任何模块之外的方法:a
字符串中没有提及模块。您在eval
上致电A.class
这一事实完全无关紧要。就像我上面所说:eval
是一个在Object
上定义的全局方法,出于方便的原因(因此可以在任何地方调用它)。您的A.class.send(:eval)
只是调用全局私有eval
方法的一种非常复杂的方式。它并没有以某种方式神奇地将eval
uated字符串的上下文设置为A.class
。
您可以改为42.send(:eval)
,结果仍然相同,就像puts('Hello')
和42.send(:puts, 'Hello')
完全相同,因为它们最终会调用完全相同的方法。< / p>
顺便说一下:即使它做了,它仍然不会做你想要的。 A.class
只是Class
(任何类的class
总是 Class
),所以如果 按预期工作,该方法将在Class
中定义,而不是在A
中定义。