Understanding Private Methods in Ruby

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

This, of course, will not work, because we specified the explicit recipient - an instance of Example ( e ), and this contradicts the "private rule".

But I cannot understand why in Ruby you cannot do this:

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

The current object inside the public_m method public_m (i.e. self ) is an instance of Foo. So why is it forbidden? To fix this, I need to change self.private_m to private_m . But why is this different and not a self instance of Foo inside public_m ? And who is the private_m voice recipient? Is it not self - in fact, you omit it because Ruby will do it for you (it will call private_m on itself)?

I hope I didn’t embarrass him too much, I still got to Ruby.




EDIT: Thanks for all the answers. By combining them all together, I was able (eventually) to reveal the obvious (and not so obvious for someone who had never seen things like Ruby): self itself can be an explicit and implicit receiver, and that makes a difference. Thus, there are two rules if you want to call a private method: self must be an implicit receiver, and that it must itself be an instance of the current class ( Example in this case), and this only happens when self if inside the definition of the instance method during execution of this method). 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 

A message to anyone who can find this question during google runs: it can be useful - http://weblog.jamisbuck.org/2007/2/23/method-visibility-in-ruby

+45
ruby access-specifier
Nov 27 '10 at 18:34
source share
6 answers

Here is short and long. What private means in Ruby is a method that cannot be called with explicit receivers, for example. some_instance.private_method (value). Therefore, although the implicit recipient is in itself, you explicitly use self in your example, so private methods are not available.

Think about it, do you assume that you can call a private method using the variable that you assigned to the class instance? No. I am a variable, so it must follow the same rules. However, when you just call the method inside the instance, it works as expected, because you are not explicitly declaring the receiver.

Ruby is that you can actually 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") } 

Hope a little more clear.

- change -

I assume you knew this would work:

 class Foo def public_m private_m # Removed self. end private def private_m puts 'Hello' end end Foo.new.public_m 
+46
Nov 27 '10 at 19:01
source share

The definition of private in Ruby is "can only be called without an explicit receiver." And so you can only use private methods without an explicit receiver. There are no other explanations.

Note that there is actually an exception to the rule: because of the ambiguity between local variables and method calls, it will always be allowed to assign a local variable:

 foo = :bar 

So what do you do if you want to name an author called foo= ? Well, you have to add an explicit receiver, because without a receiver, Ruby just won't know that you want to call the foo= method instead of assigning the local variable foo :

 self.foo = :bar 

But what will you do if you want to call the private scriptwriter named foo= ? You cannot write self.foo = because foo= is private and therefore cannot be called with an explicit receiver. Well, actually for this particular case (and only this case) you can use the explicit recipient self to call the author private .

+17
Nov 27 '10 at 21:27
source share

This is strange, but many things about Ruby visibility modifiers are strange. Even if self is an implicit receiver, in fact its use makes it explicit in the eyes of Ruby runtime. When he says that private methods cannot be called with an explicit receiver, this means that even self counts.

+13
Nov 27 '10 at 19:03
source share

IIRC, private methods only allow an implicit receiver (which is always itself, of course).

+3
Nov 27 '10 at 6:46 p.m.
source share

Sorry for my previous answer. I just do not understand your question.

I changed your code as follows:

 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 

Here is the call to the instance method:

  def public_m private_m # <= end 

Here is the class method call:

  def Foo.static_m puts "static" end def self.static2_m puts "static 2" end Foo.static_m Foo.static2_m 
+1
Nov 27 '10 at 19:10
source share

Doesn't answer the question exactly, but you can call private methods this way

 class Example private def example_test puts 'Hello' end end e = Example.new e.send(:example_test) 
0
Feb 27 '17 at 12:47 on
source share



All Articles