Bogdan Gusiev's blog

How to make good software for people


Encapsulation in Ruby: 'private' doesn't give expected level of privacy
05 Apr 2010

The classic OOP pattern usually called encapsulation implemented in ruby with private and protected keywords methods. The distinction between API and implementation works great with both. The problem is that private doesn't hide method for inherited classes.
See the simple example below:

class A
  private
  def implementation
    puts 'private A'
  end
end

class B < A
  def api
    implementation
  end
end

B.new.api
And we won't get exception at the last line.
So, in fact private do not do what you expect it to do. Use cases that distinguish private and protected are more specific. At first: implementation method can not be called like self.implementation even from class A.
class A
  def api
    self.implementation #exception here
  end
  private
  def implementation
    puts 'private A'
  end
end

A.new.api
Seamless pure gap. You can do such call if the method would be protected. Can't imagine the case when this limitation is useful.

The second difference is a bit esoteric. Two instances of the same class can access protected methods of each other but not private methods.
class A
  def api(another) #suppose to receive an instance of a
    implementation == another.implementation
  end
  protected
  def implementation
    puts 'private A'
  end
end
A.new.api(A.new)
Fine for protected but fail for private. Well, this kind of protection do not make a real because of it's rareness.

My conclusion: don't use private at all

You might do any decision on the points above.
My conclusion is to not use private at all, because it doesn't give the level of privacy that I expect. Difference form protected is so pure that it do not have any real benefits.

criticism ruby encapsulation privacy method api