了解Ruby中的私有方法

class Example private def example_test puts 'Hello' end end e = Example.new e.example_test 

这当然是行不通的,因为我们指定了示例( e )的显式接收者实例,而这是针对“私有规则”的。

但是我不明白,为什么在Ruby中不能这样做:

 class Foo def public_m self.private_m # <= end private def private_m puts 'Hello' end end Foo.new.public_m 

public_m方法定义中的当前对象(即self )是Foo的实例。 那么为什么不允许? 要解决这个问题,我必须将self.private_m更改为private_m 。 但是为什么这个不一样,是不是selfpublic_m里的Foo的一个实例呢? 谁是裸字private_m电话的接收者? 不是那个self – 你实际上忽略了什么,因为Ruby会为你做(将自己调用private_m)?

我希望我没有太多混淆,对于Ruby我还是很新鲜的。


编辑:谢谢你的所有答案。 把它们放在一起,我终于能够明白(对于从未见过像Ruby这样的人的人来说并不那么明显): self本身可以是明确的和隐含的接受者,并且能够产生变化。 所以有两个规则,如果你想调用一个私有方法: self必须是隐式的接收方,而且这个self必须是当前类的一个实例(在这种情况下是例子 – 而且只有在内部实例方法定义的时候才发生,在这个方法执行期间)。 如果我错了,请纠正我。

 class Example # self as an explicit receiver (will throw an error) def explicit self.some_private_method end # self as an implicit receiver (will be ok) def implicit some_private_method end private def some_private_method; end end Example.new.implicit 

任何人都可以在谷歌path中find这个问题的消息:这可能是有帮助的 – http://weblog.jamisbuck.org/2007/2/23/method-visibility-in-ruby

这是短而长的。 Ruby中的私有方法是不能用明确的接收方来调用的,例如some_instance.private_method(value)。 因此,即使隐式接收者是自己的,在你的例子中,你明确地使用self,所以私有方法是不可访问的。

想想这样,你会期望能够使用你已经分配给一个类的实例的variables来调用私有方法吗? 自我是一个variables,所以它必须遵循相同的规则。 然而,当你只是调用实例内的方法,那么它按预期工作,因为你没有明确声明接收器。

Ruby实际上可以使用instance_eval调用私有方法:

 class Foo private def bar(value) puts "value = #{value}" end end f = Foo.new begin f.bar("This won't work") rescue Exception=>e puts "That didn't work: #{e}" end f.instance_eval{ bar("But this does") } 

希望有一点更清楚。

– 编辑 –

我假设你知道这将工作:

 class Foo def public_m private_m # Removed self. end private def private_m puts 'Hello' end end Foo.new.public_m 

Ruby中的private 定义是“只能在没有明确接收者的情况下调用”。 这就是为什么你只能在没有明确接收者的情况下调用私有方法。 没有其他解释。

请注意,该规则实际上存在一个例外:由于局部variables和方法调用之间的不确定性,下面将始终parsing为对局部variables的赋值:

 foo = :bar 

那么,如果你想叫一个叫foo=的作家,你会怎么做呢? 那么你必须添加一个明确的接收者,因为没有接收者,Ruby根本就不知道你想调用方法foo=而不是分配给局部variablesfoo

 self.foo = :bar 

但是,如果你想打电话给一个叫做foo=private作家,你会怎么做呢? 你不能self.foo =因为foo=private ,因此不能用明确的接收者来调用。 那么,实际上对于这个特定的情况(以及这种情况),实际上可以使用明确的self接收者来调用private作家。

这很奇怪,但许多关于Ruby可见性修饰符的东西都很奇怪。 即使self是隐式的接收者,但实际上拼写出来使得它在Ruby运行时眼中是明确的。 当说私人方法不能用一个明确的接收者来调用的时候,那就是这个意思,甚至是self计数。

IIRC,私人方法允许隐式接收器(当然,它总是自我)。

对不起,我先前的答案。 我只是不明白你的问题。

我改变你的代码是这样的:

 class Foo def public_m private_m # <= end def Foo.static_m puts "static" end def self.static2_m puts "static 2" end private def private_m puts 'Hello' end end Foo.new.public_m Foo.static_m Foo.static2_m 

这里是一个实例方法的调用:

  def public_m private_m # <= end 

这里是一个类方法的调用:

  def Foo.static_m puts "static" end def self.static2_m puts "static 2" end Foo.static_m Foo.static2_m 

不完全回答问题,但可以这样调用私有方法

 class Example private def example_test puts 'Hello' end end e = Example.new e.send(:example_test)