2

这段代码将方法创建为私有方法,为什么?

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

4

1 回答 1

5

在任何模块之外定义的方法(所谓的全局方法)实际上被定义为私有实例方法Object。这样,可以在任何地方调用 (因为一切都继承自Object),并且它们只能在没有显式接收者的情况下调用。

这包括require, load, puts, print, p,gets和 等方法eval。(注:大部分其实都是在里面定义Kernel和混入Object的,但是效果和目的是一样的。)

在您的情况下,您在任何模块之外a定义一个方法:您的字符串中没有提到模块。eval你打电话的事实A.class完全无关紧要。就像我上面说的:evalObject为了方便而定义的全局方法(以便可以在任何地方调用它)。您A.class.send(:eval)只是调用全局私有eval方法的一种非常复杂的方式。它不会以某种方式神奇地将evaluated 字符串的上下文设置为A.class.

您可以42.send(:eval)改为这样做,结果仍然是相同的,就像puts('Hello')并且42.send(:puts, 'Hello')完全相同,因为它们最终调用完全相同的方法。

顺便说一句:即使它做到了,它仍然不会做你想做的事。A.class只是Class任何类的class总是,所以如果它确实按您预期的那样工作,则该方法将定义在 中,而不是在. ClassClassA

于 2012-09-20T00:09:12.897 回答