在ruby中,您使用点来调用方法,或者换句话说,将方法发送到所处理的对象。
"100".to_i
我们正在向对象“ 100”发送消息to_i
当我们这样做时:
puts "hello"
该方法将对象应用于哪个对象?
我是这样想的:
self.puts "hello"
以自我为主体的地方,例如您现在所在的环境,例如irb控制台。
但是会引发错误。
Traceback (most recent call last):
2: from /Users/albert/.rbenv/versions/2.5.0/bin/irb:11:in `<main>'
1: from (irb):17
NoMethodError (private method `puts' called for main:Object)
为什么这是错误的?方法放在哪里?
答案 0 :(得分:4)
puts
是Kernel
的模块方法。 Kernel
包含Object
,因此几乎每个类都可以使用。 puts "foo"
和Kernel.puts "foo"
是等效的。区别在于Kernel.puts
是显式的,而puts
可以调用本地定义的puts
方法。
def puts(str)
p "my puts: #{str}"
end
puts "foo"; # "my puts: foo"
Kernel.puts "foo" # foo
在幕后,Kernel.puts
呼叫$stdout.puts
。 $stdout
是IO
的预定义全局实例。
答案 1 :(得分:3)
OP的正确想法是,当省略显式接收器时,接收器变为self
。而且由于puts
在没有显式接收者的情况下工作,因此在同一环境中尝试self.puts "hello"
并不是一个坏主意。实际上,puts
是在main
上定义的,或者在给定环境中self
指向的任何对象。
这里的问题是,可以由显式接收者调用的方法是 public 方法,而方法puts
是 private 方法,拒绝显式接收者。
绕开此限制的标准方法是使用方法send
,如下所示:
self.send(:puts, "hello")
答案 2 :(得分:0)
在Ruby中,当您忽略消息发送的接收方时,隐式接收方始终为 self
。 (没有例外。)
所以,说
foo
其中foo
不是当前词法范围内的局部变量,总是等同于
self.foo
但是,有一个小问题:在Ruby中,private
方法的定义是“一种方法,只能在没有接收方的情况下发送消息才能调用该方法”。因此,尽管foo
和self.foo
在消息发送的接收方方面是等效的,但访问控制可能有所不同。特别是,如果foo
是private
,则foo
将起作用,但是self.foo
将raise
NoMethodError
消息的NoMethodError (private method `foo' called for main:Object)
异常(例如) puts
。
所以,您一直都是对的:
self.puts
等效于
private
但是您误读了错误消息:不是因为该方法不存在,而是因为该方法是Kernel
。
特别是,所有这些方法实际上更像“过程”,因为它们实际上对接收者没有任何作用,它们都定义在private
中,并定义为{{1} } 方法。这也包括Kernel#print
,Kernel#require
等方法。