В данный момент я читаю «Обоснованный рубин», и на странице 196 я вижу следующее:
Предположим, вы определили метод на верхнем уровне:
def talk
puts "Hello"
end
....
Метод, который вы определяете на верхнем уровне, сохраняется как метод частного экземпляра класса Object
.Предыдущий код эквивалентен этому:
class Object
private
def talk
puts "Hello"
end
end
...
Для иллюстрации давайте расширим пример talk
.Здесь снова, с некоторым кодом, который его реализует:
puts "Trying 'talk' with no receiver..."
talk
puts "Trying 'talk' with an explicit receiver..."
obj = Object.new
obj.talk
Первый вызов talk
успешен;второй сбой приводит к фатальной ошибке, потому что он пытается вызвать закрытый метод с явным получателем.
Я хотел воспроизвести это на своем локальном компьютере, поэтому я поместил приведенный выше код в файл 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:
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
был публичным методом в экземпляре Object
.
Мой вопрос: почему метод talk
общедоступен в классе Object, когда я реализую его непосредственно вREPL, но закрытый, когда я внедряю его в файл и загружаю в REPL (а также когда я запускаю тот же файл непосредственно в моем CLI через интерпретатор Ruby)?