Public and Private Methods in Ruby
Method Access Rules
While the end user of your program is never going to be using the methods you define in a class directly, it is still helpful to control access to your methods. Envision a team situation in which multiple developers use instances of the same class; it is useful to control which methods can be used.
A simple way to think about the difference is to imagine our class is an airplane (I’m writing this aboard one, in fact.)
Public Methods
In our Plane
class, we have a few public instance methods. We don’t need to specify that a method be public because that is their default.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
Woah, wait a second. It’s all well and good that we’re able to see what type of plane we’re working with, the fuel levels, and even whether or not we’re airborne. However, there are a few things that we definitely don’t want to be usable outside our class.
An object is easy to think about as something that does tasks for you, and its methods are the actions of doing those things. Public methods are like the API – where calls are made to the instances of the object. Private methods, on the other hand, are tasks that you might not want to be used freely. For example, the method begin_gas_combustion
is a component of the method fire_up_engine
but it’s unclear whether or not you’d want to use it in any other context. In fact, it would probably be unsafe to be able to use it in other contexts. Luckily, Ruby enables use of private methods to get around this problem.
Private Methods
A private method cannot be called with an explicit receiver. This means that if we specify begin_gas_combustion
to be a private method, we shouldn’t be able to call begin_gas_combustion
on instances of our Plane
class explicitly. Let’s rewrite a bit of our Plane class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Ok, that seems to make a bit more sense. Let’s test out our methods. If you try, you’ll get the following:
1 2 3 4 |
|
This makes sense based on our definition of private methods – the instance will
is now the explicit receiver of the method as called. However, when we try the following:
1 2 3 4 |
|
Here, since the method gets called within a public method, there is an implicit receiver – the specific instance of the object – and we are ok.
Private Setter (=) Methods
Private methods with the “no explicit receiver” rule do hit problems, however, with writer / setter methods. In these methods, you can’t use the implicit receiver because Ruby would assume you were using a local variable instead of a method without the keyword self
. Therefore, there is an exception – Ruby doesn’t apply the rule to setter methods as long as the explicit receiver is self
.
You Can Bypass Private Methods with ‘send’
Ruby has given us a way to get around our rule, however. You can always just use the send
method to send any method to any object.
Hopefully this clears up the value / usage of private methods, and see you next time.