This tutorial provides a comprehensive guide to understanding and using access modifiers in Ruby. Learn how to control the visibility of methods and attributes using `public`, `protected`, and `private` keywords. Each step builds on the previous one, with practical examples and engaging practice exercises.

Beginner30 minutes

Step 1: Understanding Access Modifiers

Access modifiers in Ruby determine the visibility of methods and attributes within a class. There are three main access levels: public, protected, and private. By default, all methods in Ruby are public unless specified otherwise.

class MyClass
  def public_method
    puts 'This is a public method'
  end

  private
  def private_method
    puts 'This is a private method'
  end
end

Practice Exercise

Create a class Person with a public method greet that prints 'Hello!' and a private method secret that prints 'This is a secret.' Call both methods from outside the class and observe the behavior.

Show Solution
class Person
  def greet
    puts 'Hello!'
  end

  private
  def secret
    puts 'This is a secret.'
  end
end

person = Person.new
person.greet  # Output: Hello!
person.secret # Error: private method `secret' called

Step 2: Using the `private` Modifier

The private modifier restricts access to methods within the class itself. Private methods cannot be called from outside the class, but they can be used internally by other methods.

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

  def show_balance
    puts "Your balance is: #{@balance}"
  end

  private
  def log_transaction
    puts 'Transaction logged'
  end
end

Practice Exercise

Create a class Calculator with a public method add that takes two numbers and returns their sum. Add a private method log_operation that prints 'Operation logged' whenever add is called.

Show Solution
class Calculator
  def add(a, b)
    log_operation
    a + b
  end

  private
  def log_operation
    puts 'Operation logged'
  end
end

calc = Calculator.new
puts calc.add(3, 4)  # Output: Operation logged
                     #         7

Step 3: Using the `protected` Modifier

The protected modifier allows methods to be accessed within the class and by instances of the same class or its subclasses. This is useful for methods that need to be shared among related objects.

class Animal
  def initialize(name)
    @name = name
  end

  protected
  def speak
    puts "#{@name} makes a sound"
  end
end

class Dog < Animal
  def bark
    speak
  end
end

Practice Exercise

Create a class Employee with a protected method calculate_bonus that returns 10% of the salary. Create a subclass Manager that overrides calculate_bonus to return 20% of the salary. Ensure the method is accessible within the class hierarchy.

Show Solution
class Employee
  def initialize(salary)
    @salary = salary
  end

  protected
  def calculate_bonus
    @salary * 0.10
  end
end

class Manager < Employee
  def calculate_bonus
    @salary * 0.20
  end
end

manager = Manager.new(50000)
puts manager.calculate_bonus  # Output: 10000.0

Step 4: Combining Access Modifiers

You can combine access modifiers within a class to create a hierarchy of visibility. For example, you might have public methods for external use, protected methods for internal use, and private methods for implementation details.

class Vehicle
  def start_engine
    puts 'Engine started'
  end

  protected
  def check_fuel
    puts 'Fuel level checked'
  end

  private
  def log_maintenance
    puts 'Maintenance logged'
  end
end

Practice Exercise

Create a class Library with a public method check_out_book, a protected method update_inventory, and a private method log_transaction. Ensure each method is used appropriately within the class.

Show Solution
class Library
  def check_out_book(book)
    update_inventory(book)
    log_transaction(book)
    puts "#{book} checked out"
  end

  protected
  def update_inventory(book)
    puts "Inventory updated for #{book}"
  end

  private
  def log_transaction(book)
    puts "Transaction logged for #{book}"
  end
end

library = Library.new
library.check_out_book('1984')  # Output: Inventory updated for 1984
                               #         Transaction logged for 1984
                               #         1984 checked out

Step 5: Real-World Application: Building a Secure System

In real-world applications, access modifiers are crucial for building secure and maintainable systems. For example, you might use private methods to handle sensitive data and protected methods to share functionality among related classes.

class User
  def initialize(username, password)
    @username = username
    @password = password
  end

  def authenticate(input_password)
    if input_password == @password
      puts 'Authentication successful'
    else
      puts 'Authentication failed'
    end
  end

  private
  def encrypt_password
    # Encryption logic here
  end
end

Practice Exercise

Create a class Bank with a public method transfer_funds that transfers money between accounts. Use a protected method validate_transaction to check if the transaction is valid and a private method log_transaction to record the transaction.

Show Solution
class Bank
  def transfer_funds(from_account, to_account, amount)
    if validate_transaction(from_account, amount)
      from_account.balance -= amount
      to_account.balance += amount
      log_transaction(from_account, to_account, amount)
      puts 'Transfer successful'
    else
      puts 'Transfer failed'
    end
  end

  protected
  def validate_transaction(account, amount)
    account.balance >= amount
  end

  private
  def log_transaction(from_account, to_account, amount)
    puts "Transaction logged: #{amount} transferred from #{from_account.id} to #{to_account.id}"
  end
end

class Account
  attr_accessor :balance, :id

  def initialize(id, balance)
    @id = id
    @balance = balance
  end
end

account1 = Account.new(1, 1000)
account2 = Account.new(2, 500)
bank = Bank.new
bank.transfer_funds(account1, account2, 200)  # Output: Transfer successful
                                             #         Transaction logged: 200 transferred from 1 to 2

Sign in to take Cornell notes on this lesson — they save automatically and stay with your account.

Sign in

Click to access the login or register cheese