I started out writing something like the following:

If I could change just one thing in ruby, I would change how private works. Aaarrgghh.

For instance, I am trying to implement an equality of bounding boxes in ruby. I would presume I could write something like:

class BoundingBox

  attr_accessor :xmin, :ymin, :xmax, :ymax

  def initialize(xmin, ymin, xmax, ymax)
    @xmin = xmin
    @ymin = ymin
    @xmax = xmax
    @ymax = ymax

  def ==(other)
    other.class == self.class && self.state == other.state
  alias_method :eql?, :==


  def state
    [@xmin, @ymin, @xmax, @ymax]


Because I am inside the scope of the class, I am allowed to access the private methods. That is how it is supposed to be. But no, ruby says something silly like:

private methods cannot be called with an explicit receiver

So you have to resort to something ludicrous like writing

  def ==(other)
    other.class == self.class && self.send(:state) == other.send(:state)

This works. So I could have left it there. But wait: protected is exactly what I want. I have been using it wrong completely.

So in short:

  • use public for your public API of your class (obviously)
  • use protected for methods that are not part of your API, but other instances of the same class need to be able to reach (e.g. for equality checking, sorting, …)
  • use private for methods that are only used inside the class, and only refer to the implicit receiver.

So if in the first example I change private to protected, it just works. I have been doing it wrong all along.