在Ruby中,应用方法放置的对象是哪个?

时间:2019-01-10 21:26:25

标签: ruby

在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)

为什么这是错误的?方法放在哪里?

3 个答案:

答案 0 :(得分:4)

putsKernel的模块方法。 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$stdoutIO的预定义全局实例。

答案 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方法的定义是“一种方法,只能在没有接收方的情况下发送消息才能调用该方法”。因此,尽管fooself.foo在消息发送的接收方方面是等效的,但访问控制可能有所不同。特别是,如果fooprivate,则foo将起作用,但是self.fooraise NoMethodError消息的NoMethodError (private method `foo' called for main:Object)异常(例如) puts

所以,您一直都是对的:

self.puts

等效于

private

但是您误读了错误消息:不是因为该方法不存在,而是因为该方法是Kernel

特别是,所有这些方法实际上更像“过程”,因为它们实际上对接收者没有任何作用,它们都定义在private中,并定义为{{1} } 方法。这也包括Kernel#printKernel#require等方法。