Lesson 3
Encapsulation, Private Attributes, and Methods
Lesson Overview

Hello! In this lesson, we're revisiting Encapsulation, Private Attributes, and Private Methods in Object-Oriented Programming (OOP). Imagine encapsulation as an invisible fence safeguarding a garden from outside interference, keeping data and methods secure within. Inside this garden, certain elements (Private Attributes and Methods) are accessible only from within the class.

These concepts are crucial for making your classes more robust and secure!

Into Encapsulation

Encapsulation in OOP wraps up data and methods into a class, making code organized and more secure. Encapsulation is essential for managing complexity and reducing errors in code. By restricting access to certain data and behaviors, we make our code more robust and easier to debug, as the class controls its own data without unintended interference from other parts of the program.

If you were coding a multiplayer game, for example, you could create a Player class that encapsulates data (health, armor, stamina) and methods (receive_damage, shield_hit, restore_health).

Ruby
1class Player 2 def initialize(health, armor, stamina) 3 @health = health 4 @armor = armor 5 @stamina = stamina 6 end 7 8 def receive_damage(damage) 9 @health -= damage # Reduce health 10 end 11 12 def shield_hit(armor) 13 @armor -= armor # Decrease armor 14 end 15 16 def restore_health(health_increase) 17 @health += health_increase # Restore health 18 end 19end 20 21player = Player.new(100, 50, 77)

Here, player is an instance of the Player class with encapsulated attributes and methods.

Private Attributes

In Ruby, attributes are private by default, and accessing them from outside the class requires attr_reader, attr_writer, or attr_accessor to define getter and setter methods. Here’s a quick recap:

  • attr_reader: Provides read-only access to an instance variable.
  • attr_writer: Provides write-only access to an instance variable.
  • attr_accessor: Provides both read and write access.

Alternatively, for more controlled access and encapsulation, we can define custom methods to interact with attributes directly. A BankAccount class might contain a balance attribute that is only accessible through specific methods like deposit or get_balance, ensuring that the balance can’t be modified in unintended ways.

Ruby
1class BankAccount 2 def initialize(account_number, balance) 3 @account_number = account_number 4 @balance = balance 5 end 6 7 def deposit(amount) 8 @balance += amount # Deposit money 9 end 10 11 def get_balance 12 @balance # Access balance 13 end 14end 15 16bank_account = BankAccount.new(1234, 100) 17puts bank_account.get_balance # Correct way to access balance 18puts bank_account.balance # Error: undefined method 'balance'

Here, balance is encapsulated, and you access it through the method get_balance, protecting its integrity.

Private Methods

Just like private attributes, Ruby makes methods private using the private keyword within the class definition. Private methods can only be called from within the class, preventing them from being accessed externally. This is helpful for tasks that should only be controlled internally.

For example, in a bank account, only the bank should be able to add interest to an account, not the account holder. We can make the add_interest method private to ensure that it can only be used internally:

Ruby
1class BankAccount 2 def initialize(account_number, balance) 3 @account_number = account_number 4 @balance = balance 5 end 6 7 # Public method calling the private method 8 def add_yearly_interest 9 add_interest(0.02) # Adds 2% interest 10 end 11 12 private 13 14 # Private method 15 def add_interest(interest_rate) 16 @balance += @balance * interest_rate # Calculation of interest 17 end 18end 19 20bank_account = BankAccount.new(1234, 100) 21bank_account.add_yearly_interest # Works for public methods 22bank_account.add_interest(0.1) # Error: private method 'add_interest' called

Here, add_yearly_interest is a public method that uses the private method add_interest. This way, the interest calculation is protected from being accessed or modified outside of the class.

Lesson Summary and Practice

Great job revisiting encapsulation, private attributes, and private methods in Ruby! By understanding and applying these core principles of OOP, you can make your code more secure, concise, and reliable. Up next is hands-on practice to deepen these skills.

Keep up the good work—exciting exercises are just around the corner!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.