Hacker News new | past | comments | ask | show | jobs | submit login

The 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/

(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.




From 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?


Ruby 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>


To be fair, you can also use reflection in Java to call private methods or access private fields, especially since they removed the security managers. Just because there are ways around it doesn't mean "it does nothing".




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: