Lesson Tuesday

Why should we bother to separate our code in classes? After all, we could just put lots of methods into the top-level scope and then just have them available all throughout an application.

By this point, we know this approach isn't a good idea. Global variables are generally bad. Variables and methods should be as tightly scoped as possible. In other words, they should only be made available to parts of the application where they are needed. If possible, methods should be used and attributes updated only in the class where they are defined.

The process of separating code out and making it available only in a single class is called encapsulation. There are a number of ways to do this in Ruby. For instance, we should always think carefully about whether an attribute should have reader and writer methods. We could easily add both to every attribute but this would be a sign of poorly-encapsulated code.

We can also make methods private, which means they can only be called inside the class where they are defined. We use the private keyword to denote which methods should be private. Here's an example:

class Car

  def start
    puts "car started!"
    inject_fuel()
  end

  private
    def inject_fuel
      puts "fuel injected!"
    end
end

In the Car class above, we have two methods. The start() method can be called outside the Car class. However, the inject_fuel() method can only be called inside the class. Let's open IRB to demonstrate what happens if we try to call both of these methods:

> car = Car.new()
> car.inject_fuel
NoMethodError: private method 'inject_fuel' called for #<Car:0x007facd880ea08>
> car.start
car started!
fuel injected!

We'll get a NoMethodError: private method 'inject_fuel' error if we try to call our private method. However, if we call the start() method, it can successfully call the inject_fuel() method because it is calling the method within the class. Our inject_fuel() method has successfully been encapsulated.

You are not expected to use the private keyword for this section's independent project. However, you're encouraged to encapsulate code where possible and to experiment with private methods. There are a few important points regarding private methods:

  • Any methods declared beneath the private keyword will be private.

  • Private methods can only be called on self implicitly. This is a bit of a tricky concept. Let's clarify what this means with another example. Let's say we update the start() method above to look like this:

def start
  puts "car started!"
  self.inject_fuel()
end

It will no longer work. This is because we've called inject_fuel() explicitly on self. We can't explicitly call inject_fuel() on self or any other variable, even if that variable happens to be an instance of Car. It can only be called implicitly on self, which is what happens when we call the method by itself inject_fuel(). self is only available implicitly within the class so it makes sense that a private method can only be called implicitly.

Benefits of Encapsulation


Encapsulating classes is considered the best, most professional practice for several reasons:

  • It allows a class to have more control over its attributes and methods, which is more secure.

  • It prevents other classes from accessing and altering attributes and methods, which can lead to difficult bugs.

  • While we may not see this benefit until our applications become larger, encapsulation leads to more maintainable code.

  • Managing all aspects of a class within the class itself leads to more organized code. Organized code allows other developers to comprehend, collaborate, and implement your logic much more easily.

Try exploring private methods in your own code and endeavor to make your code as well-encapsulated as possible.

Terminology


  • Encapsulation: The process of limiting access to fields so they are available only to a limited part of an application such as a class. It's a best practice because:

    • It allows a class to have total control over its own fields, which is more secure.
    • It prevents other classes from accessing and altering fields, which can lead to difficult bugs.
    • It leads to more maintainable and better organized code.
  • Private method: A method that can only be called inside the class where it is defined.

Example


  • To create a private method, place it below the private keyword in a class.
  • Remember that private methods can only be called implicitly on self and can't be called in any other way.

Lesson 14 of 22
Last updated August 7, 2022