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).

class Player
  def initialize(health, armor, stamina)
    @health = health
    @armor = armor
    @stamina = stamina
  end

  def receive_damage(damage)
    @health -= damage  # Reduce health
  end

  def shield_hit(armor)
    @armor -= armor  # Decrease armor
  end

  def restore_health(health_increase)
    @health += health_increase  # Restore health
  end
end

player = 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.

class BankAccount
  def initialize(account_number, balance)
    @account_number = account_number
    @balance = balance
  end

  def deposit(amount)
    @balance += amount  # Deposit money
  end

  def get_balance
    @balance  # Access balance
  end
end

bank_account = BankAccount.new(1234, 100)
puts bank_account.get_balance  # Correct way to access balance
puts 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:

class BankAccount
  def initialize(account_number, balance)
    @account_number = account_number
    @balance = balance
  end

  # Public method calling the private method
  def add_yearly_interest
    add_interest(0.02)  # Adds 2% interest
  end

  private

  # Private method
  def add_interest(interest_rate)
    @balance += @balance * interest_rate  # Calculation of interest
  end
end

bank_account = BankAccount.new(1234, 100)
bank_account.add_yearly_interest  # Works for public methods
bank_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!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal