In some cases, you may want to restrict the “visibility” of your methods to ensure that they cannot be called by code outside the class in which the methods occur.
This may be useful when your class defines various “utility” methods that it requires in order to perform certain functions that it does not intend for public consumption. By imposing access restrictions on those methods, you can prevent programmers from using them for their own nefarious purposes. This means you will be able to change the implementation of those methods at a later stage without having to worry you are going to break somebody else’s code.
Ruby provides three levels of method accessibility:
As the name suggests, public methods are the most accessible, and private methods are the least accessible. All your methods are public unless you specify otherwise. When a method is public, it is available to be used by the world outside the object in whose class it is defined.
When a method is private, it can be used only by other methods inside the object in whose class it is defined.
A protected method generally works in the same way as a private method with one tiny but important difference: In addition to being visible to the methods of the current object, a protected method is also visible to objects of the same type when the second object is within the scope of the first object.
The distinction between private and protected methods will probably be easier to understand when you see a working example. Consider this class:
pub_prot_priv.rb
class MyClass private def priv puts( "private" ) end protected def prot puts( "protected" ) end public def pub puts( "public" ) end def useOb( anOb ) anOb.pub anOb.prot anOb.priv end end
I’ve declared three methods, one for each level of accessibility. These levels are set by putting private
, protected
, or public
prior to one or more methods. The specified accessibility level remains in force for all subsequent methods until some other access level is specified.
public
, private
, and protected
may look like keywords. But they are, in fact, methods of the Module class.
Finally, my class has a public method, useOb
, which takes a MyOb
object as an argument and calls the three methods pub
, prot
, and priv
of that object. Now, let’s see how a MyClass
object can be used. First, I’ll create two instances of the class:
myob = MyClass.new myob2 = MyClass.new
Now, I try to call each of the three methods in turn:
myob.pub # This works! Prints out "public" myob.prot # This doesn't work! I get an error myob.priv # This doesn't work either - another error
From the previous, it would seem that the public method is (as expected) visible from the world outside the object to which it applies. But both the private and the protected methods are invisible. This being so, what is the protected method for? Another example should help clarify this:
myob.useOb( myob2 )
This time, I am calling the public method useOb
of the myob
object, and I am passing to it a second object, myob2
, as an argument. The important thing to note is that myob
and myob2
are instances of the same class. Now, recall what I said earlier: In addition to being visible to the methods of the current object, a protected method is also visible to objects of the same type when the second object is within the scope of the first object.
This may sound like gobbledygook. Let’s see if I can make some sense out of it. In the program, the first MyClass object (here myob
) has a second MyClass object within its scope when myob2
is passed as an argument to a method of myob
. When this happens, you can think of myob2
as being present “inside” myob
. Now myob2
shares the scope of the “containing” object, myob
. In this special circumstance—when two objects of the same class are within the scope defined by that class—the protected methods of any objects of this class become visible.
In the present case, the protected method prot
of the object myob2
(or, at any rate, of the argument that “receives” myob2
, here called anob
) becomes visible and can be executed. Its private arguments, however, are not visible:
def useOb( anOb ) anOb.pub anOb.prot # protected method can be called anOb.priv # calling a private method results in an error end
3.12.136.63