Lessons in Ruby OOP: Protected Methods

Callie Buruchara
Level Up Coding
Published in
4 min readMay 6, 2020

--

Photo by Bonnie Kittle on Unsplash

As I’ve said previously, wading through Launch School’s RB120 and the Object-Oriented Programming paradigm was simultaneously overwhelming and eye-opening. I appreciate that we had to learn everything “the hard way” in RB101 first, but it was also wonderful to gain all the tools and better-for-my-brain organization that OOP so gloriously provides.

Still, it’s quite a jump for the mind. When I was studying for the RB129 assessment, I kept getting stuck on protected methods. I understood the need for private methods and the usage of public methods; but what was the purpose of this apparently-necessary middle ground?

Before we can talk about protected methods explicitly, it’s helpful to first discuss the purpose of method access control.

Encapsulation, one of the many benefits of the OOP coding paradigm, allows us, the author of the code, to hide certain parts of our code’s functionality and then only expose what we intentionally choose to. Method access control — using public, private, or protected methods — is the tool we use to implement our intentionality.

Let’s first show how procedural programming lacks this encapsulation (contrast is the mother of clarity!). Take a look at the code below:

Special thanks to my pal Stephen for explaining encapsulation to me this way! (Who apparently learned it from Matt! So thanks, Matt!)

On line 1, we initialize local variable person and assign it to 'Sally'. We can immediately output it on line 2 — meaning, there’s nothing protecting it or preventing us from accessing it. On line 5, we see that we can even change the value of the variable. Again, nothing is protecting this local variable from access or manipulation. With a more complicated program, we would run into scoping issues that could prevent us from manipulating variables, but that’s more of a consequence of initialization location rather than an intentional protection.

What if we wanted to protect person? What if we wanted to use it for functionality but not let anyone see it directly, or at least not change it?

Enter OOP! (cue heroic music)

Encapsulation allows us to intentionally hide or expose the functionality of our code. Instead of allowing it all to be exposed and vulnerable , we can make intentional choices.

This happens as soon as we bring classes into our code:

Within our Person class, we use our constructor (initialize) to receive an argument and assign it to a @name instance variable for our new Person object. Now, if we want to access that name, we have to intentionally create a way to do so. We haven’t yet, so line 8 doesn’t give us the name. But if we do this:

On line 2, we created a getter method with our attr_reader. We can now access the name of our Person object, because we intentionally created a way for us to do so. Great!

But let’s say we have a more complicated example. We have code that we want to use in an instance method, but we don’t want it to be accessible to the rest of the codebase. For example:

Here we have a Dog class that has an older? instance method that compares the ages of two objects. This code works fine!

What if we didn’t want the world to know sadie's age, though? She’s getting older, she’s a self conscious sweet thing, so we want to respect her privacy. We still want to know if she’s older than another dog, but we don’t need to know her exact age. We can leave that part to mystery.

Since we want privacy, we might try to reach for the private keyword. However if we do that, we won’t be able to call age on other on line 8. Why? Because with private methods, you cannot use them on an explicit caller (of which other is trying to be an explicit caller)¹. So since we (a) want to use the age getter method inside the class on an explicit caller and (b) don’t want the age getter method to be available outside the class, we can use… protected methods!

Now we can do exactly what we wanted to.

In summary, protected methods are a part of encapsulation, and they allow you to use methods like they’re public methods inside the class (can use them with explicit callers, etc.), and they’ll restrict access and be treated like private methods outside of the class.

I hope this was helpful!. If you’re a fellow Launch School student and want to talk through these concepts or anything else in OOP, feel free to reach out to me on Slack! Onwards and upwards, fellow learners.

[1] Since Ruby 2.7, you can call private methods on an explicit receiver, but only if that receiver is self…but that’s an article for another time

--

--