理解 Ruby 中的私有方法 [英] Understanding private methods in Ruby

查看:28
本文介绍了理解 Ruby 中的私有方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

class Example
 private
 def example_test
  puts 'Hello'
 end
end

e = Example.new
e.example_test

这当然行不通,因为我们指定了显式接收器 - Example (e) 的实例,这违反了私有规则".

This of course will not work, because we specified explicit receiver - instance of Example (e), and that is against a "private rule".

但我不明白,为什么不能在 Ruby 中做到这一点:

But I cannot understand, why one cannot do in Ruby this:

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.但是为什么这不同,self 不是 public_m 中的 Foo 实例吗?谁是裸字 private_m 调用的接收者?那不是 self - 实际上你忽略了什么,因为 Ruby 会为你做这件事(会在 self 上调用 private_m)?

The current object inside public_m method definition (i.e. self) is the instance of Foo. So why it is not allowed? To fix that I have to change self.private_m to just private_m. But why this differ, isn't the self an instance of Foo inside public_m? And who is the receiver of bare-word private_m call? Isn't that self - what actually you omit because, Ruby will do it for you (will call private_m on self)?

我希望我没有把它混淆太多,我对 Ruby 还很陌生.

I hope I didn't confuse it too much, I am still fresh to Ruby.

谢谢大家的回答.将它们放在一起,我能够(最终)理解显而易见的(对于从未见过像 Ruby 这样的东西的人来说并不那么明显):self 本身可以是显式和隐式接收器,这有所作为.所以有两个规则,如果你想调用一个私有方法:self 必须是隐式接收者,并且那个 self 必须是当前类的实例(Example 在这种情况下- 并且只有在 self if 在实例方法定义中时才会发生,在此方法执行期间).如果我错了,请纠正我.

Thank you for all the answers. Putting them all together I was able (finally) to grok the obvious (and not so obvious for someone, who have never seen things like Ruby): that self itself can be explicit and implicit receiver and that make the difference. So there are two rules, if you want to call a private method: self must be implicit receiver, and that self must be an instance of current class (Example in that case - and that takes place only when self if inside instance method definition, during this method execution). Please correct me if I am wrong.

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

给在 google trails 中发现这个问题的任何人的信息:这可能会有所帮助 - http://weblog.jamisbuck.org/2007/2/23/method-visibility-in-ruby

Message for anyone who could find this question during the google trails: this may be helpful - http://weblog.jamisbuck.org/2007/2/23/method-visibility-in-ruby

推荐答案

这里是长篇和短篇.Ruby 中的私有意味着不能使用显式接收器调用方法,例如some_instance.private_method(value).因此,即使隐式接收器是 self,在您的示例中,您也显式使用 self,因此无法访问私有方法.

Here's the short and the long of it. What private means in Ruby is a method cannot be called with an explicit receivers, e.g. some_instance.private_method(value). So even though the implicit receiver is self, in your example you explicitly use self so the private methods are not accessible.

这样想,您是否希望能够使用分配给类实例的变量来调用私有方法?不. Self 是一个变量,所以它必须遵循相同的规则.但是,当您只是在实例内部调用该方法时,它会按预期工作,因为您没有显式声明接收器.

Think of it this way, would you expect to be able to call a private method using a variable that you have assigned to an instance of a class? No. Self is a variable so it has to follow the same rules. However when you just call the method inside the instance then it works as expected because you aren't explicitly declaring the receiver.

Ruby 就是这样,您实际上可以使用 instance_eval 调用私有方法:

Ruby being what it is you actually can call private methods using 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") }

希望说得更清楚一点.

-- 编辑--

我假设你知道这会奏效:

I'm assuming you knew this will work:

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

Foo.new.public_m

这篇关于理解 Ruby 中的私有方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆