当我在 IRB 中声明时,为什么我的顶级方法 public(相对于私有)在所有 类 上?

Why is my top-level method public (as opposed to private) on all classes when I declare it in IRB?

我正在阅读 "The Well-Grounded Rubyist",在第 196 页我看到以下内容:

Suppose you define a method at the top level:

def talk
  puts "Hello"
end

....

A method that you define at the top level is stored as a private instance method of the Object class. The previous code is equivalent to this:

class Object

  private

  def talk
    puts "Hello"
  end
end

...

To illustrate, let's extend the talk example. Here it is again, with some code that exercises it:

puts "Trying 'talk' with no receiver..."
talk
puts "Trying 'talk' with an explicit receiver..."
obj = Object.new
obj.talk

The first call to talk succeeds; the second fails with a fatal error, because it tries to call a private method with an explicit receiver.

我想在我的本地复制这个,所以我把上面的代码放在我创建的 Ruby 文件中。我确实得到了书中提到的结果:

$ ruby talk.rb 
Trying 'talk' with no receiver...
Hello
Trying 'talk' with an explicit receiver...
Traceback (most recent call last):
talk.rb:22:in `<main>': private method `talk' called for #<Object:0x00007f9a8499c3e0> (NoMethodError)

我还尝试了以下方法,它产生了与通过 Ruby 解释器 运行ning 代码相同的错误:

irb(main):008:0> load 'talk.rb'
Trying 'talk' with no receiver...
Hello
Trying 'talk' with an explicit receiver...
Traceback (most recent call last):
        4: from /Users/richiethomas/.rbenv/versions/2.5.3/bin/irb:11:in `<main>'
        3: from (irb):8
        2: from (irb):8:in `load'
        1: from talk.rb:22:in `<top (required)>'
NoMethodError (private method `talk' called for #<Object:0x00007ffb219c95e0>)

接下来,我在irb中尝试了相同的代码,这次我得到了以下奇怪的结果:

irb(main):001:0> def talk
irb(main):002:1> puts "Hello"
irb(main):003:1> end
=> :talk
irb(main):004:0> puts "Trying 'talk' with no receiver..."
Trying 'talk' with no receiver...
=> nil
irb(main):005:0> talk
Hello
=> nil
irb(main):006:0> puts "Trying 'talk' with an explicit receiver..."
Trying 'talk' with an explicit receiver...
=> nil
irb(main):007:0> Object.new.talk
Hello
=> nil

如您所见,在最后一个代码示例中,我能够调用 Object.new.talk 并让它打印 Hello 就好像 .talk 是一个 public 方法在 Object 实例上。

我的问题是 - 为什么 talk 方法 public 在对象 class 上直接在 REPL 中实现它,但在文件中实现它时是私有的并且将它加载到 REPL 中(以及当我通过 Ruby 解释器直接在我的 CLI 中 运行 相同的文件时)?

irbpry旁注:我强烈建议使用后者)调整他们的输入以将所有方法声明为public(在 E 阶段 REP 循环):

▶ def foo; end
#⇒ :foo
▶ public_methods.grep /foo/
#⇒ [:foo]

就是这样,没有魔法。


这样做主要是为了简化在此处定义方法然后希望可以从例如那里。在 REPL 让一切随处可用是值得的。

def pretty_print; self.inspect; end
class A; ...; end
class B; ...; end

A.new.pretty_print
B.new.pretty_print

玩沙盒的时候不要太在意封装、SRP等问题


一般来说,这就像用通用助手声明模块并免费将其包含在任何地方。