如果“puts”方法是私有实例方法,为什么我们可以从任何地方调用它?

时间:2013-11-18 05:55:36

标签: ruby

我已经读过“puts”是模块内核的私有实例方法(因此是Object的私有实例方法,因为Object混合在Kernel中)。

这就是为什么当我们调用puts时,我们没有指定显式接收器。我的问题是,如果它是一个私有实例方法,我们怎么可能从任何其他范围调用它?所以,我们可以这样做:

class Test 
  puts "hello" # self is Test. So, we are calling self.puts "hello" -
end

我在这里缺少什么?这怎么可能有效呢?我们正在调用私有实例方法吗?

编辑:

如果我这样做,就会出现同样的问题:

class Object
  private
  def talk
    puts "hi there"
  end
end

class Test
  talk # outputs 'hi there'
end

为什么从类Test可以调用Object类中的私有方法?

2 个答案:

答案 0 :(得分:3)

请查看内核模块的文档 - http://www.ruby-doc.org/core-2.0.0/Kernel.html

与Java不同,Ruby不仅限于Classes作为实现的容器。模块充当了很好的容器,可以混合到其他类中。当一个模块混合到另一个类中时,它的所有实例方法都成为这些类的实例方法。由于内核模块混合到Object类中,因此它的方法可用于所有Ruby类。

请阅读以下内容:

  1. Ruby access control
  2. Common misunderstanding and clarification about access controls in Ruby
  3. 由于存在重复的风险,我不得不说:Ruby中的private与C ++或Java中的不同。类的子类可以调用在其超类中声明的私有方法。实际上,您可以使用:send调用任何类的私有方法。 私有方法和受保护方法之间的唯一区别是无法使用显式接收器调用私有方法。

    即使是最后一条规则也有例外。如果您的私有方法类似于age=,则可以(并且必须)使用self调用它。好笑,不是吗? :)

    更新:(解释要点):

    您在上面的代码中编写的talk方法正在main对象上调用,该对象是所有Ruby程序的上下文。它没有在Test类中被调用,这就是为什么它不能用于你的第二个要点。

    在我提供的要点中,talk是一个私有类方法,这就是它在类定义时执行的原因。在同一个要点中,talk2方法是一个实例方法,只能从实例方法中调用。您的示例gist不起作用,因为您在定义类时尝试调用实例方法。

答案 1 :(得分:0)

我不明白为什么在其他答案中需要这么长的答案,或者被投票赞成。你的问题的答案很简单。

这是因为几乎所有类(即BasicObject以外的任何类)都包含Kernel。因此,在通常对象的范围内,继承Kernel类,因此可以访问其方法。就是这样。