Menu
Coddy logo textTech

Private Methods

Part of the Object Oriented Programming section of Coddy's Ruby journey. Lesson 17 of 57.

Encapsulation means an object hides how it works and offers a small set of public methods. Methods are public by default. Every method defined after the word private in a class body is private: the object's own methods can call it, outside code cannot:

class Order
  def initialize(price, quantity)
    @price = price
    @quantity = quantity
  end

  def total
    subtotal + shipping
  end

  private

  def subtotal
    @price * @quantity
  end

  def shipping
    subtotal >= 50 ? 0 : 5
  end
end

order = Order.new(10, 3)
puts order.total
begin
  order.subtotal
rescue NoMethodError => e
  puts e.message
end

Output:

35
private method `subtotal' called for an instance of Order

Inside the class, a private method is called without a receiver or with self.. Calling it on another object, even one of the same class, is refused:

class Coin
  def initialize(cents)
    @cents = cents
  end

  def describe
    "#{self.label} / #{label}"
  end

  def same_as?(other)
    other.label == label
  end

  private

  def label
    "#{@cents}c"
  end
end

a = Coin.new(5)
puts a.describe
begin
  a.same_as?(Coin.new(5))
rescue NoMethodError => e
  puts e.message
end

Output:

5c / 5c
private method `label' called for an instance of Coin

private can also take a method name, and def returns the method's name, so private def helper makes a single method private right where it is defined. The methods above and around it stay public:

class Greeter
  def greet(name)
    "#{salutation}, #{name}!"
  end

  private def salutation
    "Hello"
  end

  def wave
    "*waves*"
  end
end

g = Greeter.new
puts g.greet("Ada")
puts g.wave
p Greeter.private_instance_methods(false)

Output:

Hello, Ada!
*waves*
[:salutation]

Keep helpers private. The public methods are the promise a class makes to the rest of the program; private ones can be renamed or removed later without breaking any caller:

class Invoice
  def total              # public: callers rely on it
    net + tax
  end

  private                # free to change later

  def net
    ...
  end

  def tax
    ...
  end
end
challenge icon

Challenge

Easy

Complete the class Order. Its only public method besides initialize is receipt, which returns 3 x 12.50 = 37.50, tax 7.50, total 45.00. The private methods subtotal (price times quantity), tax (20% of the subtotal) and total compute the numbers.

The supplied code reads orders as quantity price lines and prints each receipt. Then it tries to call tax from outside and prints tax is private when Ruby refuses.

Your code goes in order.rb. main.rb holds the supplied input/output code and cannot be edited.

Try it yourself

require_relative 'order'

# Supplied input/output code: keep it as it is
input = []
while (line = gets)
  input << line.chomp
end
orders = input.map do |line|
  quantity, price = line.split
  Order.new(quantity.to_i, price.to_f)
end
orders.each { |o| puts o.receipt }
begin
  orders[0].tax
  puts "tax is public"
rescue NoMethodError
  puts "tax is private"
end
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming

Practice on your own: Online Ruby compiler