I'm currently reading "The Well-Grounded Rubyist", and on page 196 I see the following:
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.
I wanted to reproduce this on my local, so I put the above code in a Ruby file I created. I did indeed get the results mentioned in the book:
$ 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)
I also tried the following, which produced the same error as running the code via the Ruby interpreter:
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>)
Next, I tried the same code in irb
, and this time I got the following strange results:
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
As you can see, in the last code example, I was able to call Object.new.talk
and have it print Hello
as if .talk
were a public method on the Object
instance.
My question is- why is the talk
method public on the Object class when I implement it directly in the REPL, but private when I implement it in a file and load it into the REPL (and also when I run that same file directly in my CLI via the Ruby interpreter)?