4 ms·
Sorry, that’s simply a typo translating from Java to Ruby. I believe the point that section is trying to make still holds after editing it to say “private :x, :
by jez 3y ago
Sorry, that’s simply a typo translating from Java to Ruby. I believe the point that section is trying to make still holds after editing it to say “private :x, :x=”
> Private methods can only be invoked on an implicit receiver.
This changed in Ruby 2.7. You can now include the self keyword, which is important because it allows calling methods that share names with Ruby keywords. “begin” is a keyword but “self.begin” is a call to a method named begin. So if that method happens to be private, you can call it now in Ruby 2.7 without needing “send(:begin)”
Other than the typo (thanks! I’ll fix that when I’m back at my computer), I think that the rest of the post underscores what you’ve already pointed out about how private works, modulo the misunderstanding about the changes in Ruby 2.7
- stouset 3y agoAha! Glad I caveated things by saying I may have missed a change in semantics. I’m surprised they did that in a minor release and not a major one. So, then, is there no actual difference between private and protected now?
- jez 3y agoThe difference between private and protected is a bit subtle so I’ll defer to the Ruby FAQ: https://www.ruby-lang.org/en/documentation/faq/7/ https://www.ruby-lang.org/en/documentation/faq/7/ (On this page there’s a section called “What’s the difference between private and protected?” which explains it.) It’s interesting in its own right, and it’s in my backlog to blog about because I don’t like any of the existing resources contrasting the two.
- tsimionescu 3y agoFrom the examples in this FAQ, it seems like protected works a bit more like Java's private - you can use it only inside the class, but for any object of that class, not just self, right? (with the exception that it applies to subclasses) So Ruby's private only allows you to interact with other methods on the current object. Protected allows objects of the same class to send each other the message, but not other classes. Would this be a fair summary?
- arthurcolle 3y agoRuby private literally does nothing. It's a marker with some side effects, but isn't actually protecting anything. You can trivially do obj.send(:private_method) for any method, private or not. It's been about a year since I last looked at Ruby code (a true fave, holds it down, easy to love), but I'm pretty sure that's the idea. In Ruby, the private keyword is more about controlling the visibility of methods rather than providing strict access control. It's a part of Ruby's philosophy of "convention over enforcement." While it does mark methods as private, it doesn't prevent you from calling them using .send. This is a design choice in Ruby to prioritize flexibility and programmer discretion. Here's a bit more detail on how it works: Method Visibility: When you declare a method as private, you're essentially saying that it should only be used within the class where it's defined (or its subclasses). This is a way to indicate the intended usage of a method. No Strict Access Control: Unlike some other languages, Ruby doesn't enforce strict access control. It trusts the developer to follow conventions. However, this doesn't mean you should casually break encapsulation. It's a matter of design and discipline. send and public_send: The send method allows you to invoke any method, including private ones, on an object. It's a powerful feature that can be handy in some situations but should be used with caution. There's also public_send, which respects the visibility rules and won't invoke private methods. Here's an example: class MyClass def public_method puts "This is a public method" end private def private_method puts "This is a private method" end end obj = MyClass.new obj.public_method # works, prints the string obj.private_method # fails, no method irb(main):014:0> obj = MyClass.new => #<MyClass:0x00000001368fd6d0> irb(main):015:0> obj.public_method This is a public method => nil irb(main):016:0> obj.private_method Traceback (most recent call last): 4: from /usr/bin/irb:23:in `<main>' 3: from /usr/bin/irb:23:in `load' 2: from /Library/Ruby/Gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>' 1: from (irb):16 NoMethodError (private method `private_method' called for #<MyClass:0x00000001368fd6d0>) Did you mean? private_methods irb(main):017:0> obj.send(:private_method) This is a private method => nil irb(main):018:0>
- tsimionescu 3y ago
- mst 3y ago> I’m surprised they did that in a minor release and not a major one. I think allowing it on self. can be argued to be a pure feature -addition- rather than a -change- in which case it being in a minor release is reasonable. (I'm not sure to what extent I buy that argument, but it at least seems like a reasonable one to make)
- djur 3y agoAlong these lines, I have a nit to pick: "private" isn't a keyword in Ruby. It's just a method on Module.