Ruby 在 irb 中和源文件中直接定义方法不同?

maxchen · 2018年11月03日 · 最后由 heroyct 回复于 2018年11月04日 · 1502 次阅读

假如在 irb 和源文件中分别定义一个 :meet 方法:

def meet
    puts in main
end

在 irb 中定义这个方法会使得 irb 中的所有对象都会拥有这个:meet 方法

当是源文件中定义却不会,为什么会这样呢?

文件中,在顶级作用域中定义的方法会成为 Object 的 private 方法,所以你在文件中定义 meet,所有对象也会继承这个方法,只是它是 private 的,调用时要省略调用者,或者使用 send。而在 irb 的顶级作用域中定义的方法会成为 Object 的 public 方法,所以你可以直接显式调用。至于为什么会有这样的处理方式,我也木有看过比较权威的说法😕

顶级作用域中定义的方法会成为 Object 的 private 方法,和下面的定义一样

class Object
  private

  def meet
    puts in main
  end
end

几乎所有对象,类都继承于 Object,所以他们也间接的拥有了私有方法 meet

#                            +---------+             +-...
#                            |         |             |
#            BasicObject-----|-->(BasicObject)-------|-...
#                ^           |         ^             |
#                |           |         |             |
#             Object---------|----->(Object)---------|-...
#                ^           |         ^             |
#                |           |         |             |
#                +-------+   |         +--------+    |
#                |       |   |         |        |    |
#                |    Module-|---------|--->(Module)-|-...
#                |       ^   |         |        ^    |
#                |       |   |         |        |    |
#                |     Class-|---------|---->(Class)-|-...
#                |       ^   |         |        ^    |
#                |       +---+         |        +----+
#                |                     |
#   obj--->OtherClass---------->(OtherClass)-----------...

源文件中定义也是一样的,我是这样测试的

1. 写个 test.rb 文件

def meet
  puts '213'
end

meet

obj = Object.new
obj.meet

2. 执行以后可以发现一般的对象也拥有了 meet 私有方法

$ ruby test.rb
213
test.rb:8:in `<main>': private method `meet' called for #<Object:0x007fda1107c4f0> (NoMethodError)
需要 登录 后方可回复, 如果你还没有账号请 注册新账号