When designing a class interface, it's important to consider just how
much access to your class you'll be exposing to the outside world.
Allow too much access into your class, and you risk increasing the
coupling in your application---users of your class will be tempted to
rely on details of your class's implementation, rather than on its
logical interface. The good news is that the only way to change an
object's state in Ruby is by calling one of its methods. Control
access to the methods and you've controlled access to the object.
A good rule of thumb is never to expose methods that could leave an
object in an invalid state. Ruby gives us three levels of protection.
- Public methods can be called by anyone---there is no
access control. Methods are public by default (except for
initialize, which is always private).
- Protected methods can be invoked only by objects of the
defining class and its subclasses. Access is kept within the family.
- Private methods cannot be called with an explicit
receiver. Because you cannot specify an object when using them,
private methods can be called only in the defining class and by
direct descendents within that same object.
The difference between ``protected'' and ``private'' is fairly subtle,
and is different in Ruby than in most common OO languages. If a method is
protected, it may be called by any
instance of the defining
class or its subclasses. If a method is private, it may be called only
within the context of the calling object---it is never possible to
access another object's private methods directly, even if the object
is of the same class as the caller.
Ruby differs from other OO languages in another important way. Access
control is determined dynamically, as the program runs, not
statically. You will get an access violation only when the code
attempts to execute the restricted method.