ruby - 关于 ruby​​ 'main' 对象的不一致

标签 ruby metaprogramming

Ruby 在类和对象方面非常一致。然而,当涉及到顶级方法声明时,该规则不知何故被打破了。例如,

$ puts self # => main
$ puts self.class # => Object

但是,在此 main 对象的上下文中声明的方法以某种方式可用作类 Object 的私有(private)方法。

这有什么合乎逻辑的解释吗?我知道这非常方便,因为这些方法显示为“独立函数”,但将其视为“就是这样”会破坏其他一致的规则,因为通常您必须在类的上下文中定义方法因为它是那个类的一个方法。但是,main 对象不是类 Object,也根本不是类。

重新构建我的问题: 该方法在什么范围内在 ruby​​ 的 REPL 中声明? {class Object/object main or module Kernel}

关于在 REPL 中声明的方法的私有(private)性质,请看下面的例子:

def my_method # "a method declared in REPL"
  puts "method called"
end

# calling my_method in REPL aka top-level scope
my_method # => "method called"
[].my_method # => private method `my_method' called for []:Array (NoMethodError)
Array.my_method # => private method `my_method' called for Array:Class (NoMethodError)

问:如果my_method定义为Object类下的私有(private)方法,为什么self设置为main而不是Object类。如果有人说它不在私有(private)范围内,那么为什么我会收到上述错误?

最佳答案

虽然我不确定我是否完全理解这个问题,但我会尝试回答:

当你在 irb 中工作时,你实际上是在这样的环境中工作:

class Object
  # you're here
end

因此,如果您在 REPL 中声明一个方法,您实际上是在 main 的类中声明它:

ruby-1.9.3-rc1 :001 > def foo; end
 => nil 
ruby-1.9.3-rc1 :002 > self.class.public_methods.include?(:foo)
 => true 

我不确定您是从哪里了解到那里定义的方法是类私有(private)的(但同样,我可能误解了这个问题)。

您在 irb 中的类包括 Kernel 模块,因此您可以访问它的功能(因为您在类中,所以出现作为独立函数,即使它们是常规方法):

ruby-1.9.3-rc1 :003 > self.class.included_modules
 => [Kernel] 

这将使它与典型的 Ruby 行为保持一致,事实上,main 只是 Object 类中的 self

如果您调用 self,您将收到 main,因为这是指示通过检查执行此操作的方式。我们可以从 self 中删除 #to_s 方法并查看实际值:

ruby-1.9.3-p0 :001 > self
 => main 
ruby-1.9.3-p0 :002 > class << self; remove_method :to_s; end
 => #<Class:#<Object:0x007fc08387af00>> 
ruby-1.9.3-p0 :003 > self
 => #<Object:0x007fc08387af00 @prompt={:PROMPT_I=>"ruby-1.9.3-p0 :%03n > ", :PROMPT_S=>"ruby-1.9.3-p0 :%03n%l> ", :PROMPT_C=>"ruby-1.9.3-p0 :%03n > ", :PROMPT_N=>"ruby-1.9.3-p0 :%03n?> ", :RETURN=>" => %s \n", :AUTO_INDENT=>true}> 

编辑:在继续之前,我认为您应该弄清楚您使用的是哪个 Ruby 版本,请参阅下面的 1.9.3 示例:

ruby-1.9.3-p0 :001 > def my_method
ruby-1.9.3-p0 :002?>     puts "method called"
ruby-1.9.3-p0 :003?> end
 => nil 
ruby-1.9.3-p0 :004 > 
ruby-1.9.3-p0 :005 >   [].my_method
method called
 => nil 
ruby-1.9.3-p0 :006 > Array.my_method 
method called

关于ruby - 关于 ruby​​ 'main' 对象的不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11474610/

相关文章:

ruby - 如何检查变量是否真的 responds_to :dup?

ruby - rails 3 : Do i need to give return true in a before_save callback for an object. 保存工作?

ruby - 使用方法参数引用 YAML 节点

ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法?

c - 知道 void * 分配类型的宏

ruby-on-rails - 如何使用线程池写入我的数据库?

python - 获取函数的包含上下文

c++ - 检测 SFINAE 的 POD 类型的第一个成员

javascript - 有没有办法在 Typescript 的包装函数中动态键入函数?

grails - 如何保存方法以备后用,将其 stub 一段时间?