新手问题 新手求教,关于 main 对象的一些疑问

z_ach · 2016年02月23日 · 最后由 rei 回复于 2016年02月24日 · 1840 次阅读

今天发现在顶层可以直接使用 include

module D
  private
  def hello
    puts "hello"
  end
end

include D
p self.class.ancestors  # [Object, D, Kernel, BasicObject]
hello # hello

然后我把 main 对象和 Object 对象在 pry 里比较了一下,发现多出五个私有方法 [:include, :using, :public, :private, :define_method],好像都是 Module 里的方法 我想问的是,main 的祖先链里并没有 Module,这几个方法是怎么进去的?还有为什么要在 main 里加上这些方法?

Kernel 不是 module? http://ruby-doc.org/core-2.3.0/Kernel.html The Kernel module is included by class Object, so its methods are available in every Ruby object.

#1 楼 @chenjau 我说的是 Module, 不是 Module 的实例,Kernel 实例方法里没有 :include, :using, :public, :private, :define_method

main 的祖先链里并没有 Module,这几个方法是怎么进去的?

这几个方法是 main 对象的 private singleton method,定义在 main 对象的 metaclass 里,因此可以被 main 对象调用

# at top-level
self.private_methods - Object.private_instance_methods  # => [:define_method, :include, :private, :public, :using]

self.singleton_class.private_instance_methods(false) #=> [:define_method, :include, :private, :public, :using]

为什么要在 main 里加上这些方法?

个人感觉可以用四个字形容:将错就错。Ruby 也不是一门完美的语言,top-level 的设计一直也来也很有争议。顶层的 main 对象时而表现得像一个 Object 类的普通实例,时而表现得像一个 Module。严谨地讲,这是 Ruby 的一个 bug,然而 Matz 并不准备改,所以只能将错就错下去了。

更多讨论:

Rubinius 源码: https://github.com/rubinius/rubinius/blob/master/core/main.rb

#3 楼 @fighterleslie 谢谢!涨姿势了。我之前一直以为 top level 就是在 main 对象上的 instance_eval 块

新手别研究这些东西,到现在我也怎么没用过这些方法

顶层 include 的作用是让顶层可以使用 DSL。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号