Private Methods in C++ and Ruby

I’ve recently had to re-learn the meanings of protected and private accessibility for Ruby methods, and how those meanings differ from the same keywords in C++, and so I thought I’d summarize what I’ve learned here. Note that to keep things as simple as possible, I’m ignoring the exceptions to these rules for C++ that friend classes introduce.

First, the good news. As far as I can determine, everything that you know about protected member functions in C++ classes applies to protected methods in Ruby classes. That is to say, a protected method can be called from other methods in the same class, as well as from methods in derived classes. Also, one instance of a class can call protected methods on other instances of the same class.

There are some subtle differences, however, when it comes to private member functions and methods. In C++, a private member function can only be called from member functions of the class in which it’s declared. So if you declare a private member function foo() in a base class:

This brings us to the first difference between private member functions in C++ and private methods in Ruby, and it has to do with the visibility of private methods in derived classes. As we’ve just seen, C++ private member functions are not visible in derived classes. In Ruby, however, private methods are visible in derived classes, i.e. if foo is declared private in the base class:

class Base
private
def foo; end
end

then methods in the derived class can call it:

class Derived < Base
def bar
foo # this is allowed in Ruby
end
end

The next difference between private member functions in C++ and private methods in Ruby has to do with the objects on which the private member function (or method) can be called. In C++, you can call a private member function on any instance of the class that declares that member function, e.g.

In Ruby, you can’t specify the receiver when calling a private method. Put another way, you can only call a private method on self, either implicitly or explicitly, e.g.

class Base
private
def foo; end
public
def spam(otherObject)
foo # this is allowed in Ruby (self is implicit)
self.foo # so is this
otherObject.foo # but this isn't
end
end

In C++, one would choose the private access over protected access for a member function to better enforce data hiding: the less that derived classes “know” about the base class implementation, the better. In Ruby, however, there doesn’t seem to be any direct way to hide base class methods from derived classes. One person summed up the distinctions by saying that in C++, “private” means “private to this class”, while in Ruby it means “private to this instance”.