Reason #89 • March 30th, 2026

Nothing is private

In most object-oriented programming languages, there is a strong emphasis on encapsulation: the idea that an object's internal state and implementation details should be hidden from the outside world. This is often achieved through access modifiers like private, protected and public, which control the visibility of methods and properties.

Nothing wrong with that in general, and Ruby provides private and protected directives and instance variables as well.

However, there is a big difference in how these boundaries are enforced in Ruby compared to languages like Java or C++. In Ruby, the private keyword is more of a convention than an access control mechanism. It does prevent you from calling into internals from outside the class, but it also provides ways to bypass this restriction if you really want to:

Ruby
class MyClass
  def initialize
    @instance_variable = "This is private"
  end

  def public_method
    "This is a public method"
  end

  private

  def private_method
    "This is a private method"
  end
end

instance = MyClass.new

instance.public_method
# => "This is a public method"

instance.private_method
# => NoMethodError: private method `private_method' called for ...

instance.send(:private_method)
# => "This is a private method"

instance.instance_variable_get(:@instance_variable)
# => "This is private"
    

In Ruby, you can use Object#send to call private methods, and Object#instance_variable_get to access instance variables. The implication is that Ruby gives the programmer full authority over the running code. In practice, this reduces friction when introspecting and debugging and enables the possibility of quick and dirty patches when necessary.

It sure feels good and empowering to be trusted in this way!

Reason #90 ?