Menu
Coddy logo textTech

Methods and self

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

A method can call another method of the same object without writing a receiver. Ruby sends the call to the current object, so methods build on each other:

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

  def subtotal
    @price * @quantity
  end

  def shipping
    subtotal >= 50 ? 0 : 5
  end

  def total
    subtotal + shipping
  end
end

puts Order.new(10, 3).total
puts Order.new(20, 3).total

Output:

35
60

Inside a method, self is the object the method was called on. A method that returns self lets the caller chain several calls on the same object:

class Counter
  def initialize
    @count = 0
  end

  def add(n)
    @count += n
    self
  end

  def count
    @count
  end
end

puts Counter.new.add(2).add(5).count

Output:

7

An object can also hand itself to other code with self, for example to return the winner of a comparison with another object of the same class:

class Player
  def initialize(name, score)
    @name = name
    @score = score
  end

  def name
    @name
  end

  def score
    @score
  end

  def winner_against(other)
    score >= other.score ? self : other
  end
end

ada = Player.new("Ada", 9)
bo = Player.new("Bo", 7)
puts ada.winner_against(bo).name
puts bo.winner_against(ada).name

Output:

Ada
Ada

Method names that answer a yes-or-no question end in ?, like empty?. Parameters can have default values, used when the caller leaves the argument out:

class Kettle
  def initialize
    @temp = 20
  end

  def hot?
    @temp >= 90
  end

  def heat(degrees = 10)
    @temp = [@temp + degrees, 100].min
  end
end

k = Kettle.new
k.heat
puts k.hot?
k.heat(75)
puts k.hot?

Output:

false
true
challenge icon

Challenge

Easy

Complete the class ShoppingCart. add(name, price) stores an item and returns the cart itself, so the calls can be chained. total returns the sum of the prices, free_shipping? returns true from a total of 20, and summary returns 3 items, total 12.50 (or 1 item, total 4.00), with two decimals.

The supplied code adds one item per input line (name price) by chaining the calls, then prints summary and free shipping: true or free shipping: false.

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

Try it yourself

require_relative 'shopping_cart'

# Supplied input/output code: keep it as it is
input = []
while (line = gets)
  input << line.chomp
end
cart = input.reduce(ShoppingCart.new) do |c, line|
  name, price = line.split
  c.add(name, price.to_f)
end
puts cart.summary
puts "free shipping: #{cart.free_shipping?}"
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