Menu
Coddy logo textTech

Readers and Writers

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

Writing a reader method for every instance variable is repetitive. attr_reader :title in the class body generates the method title, which returns @title. One line can list several names:

class Book
  attr_reader :title, :pages

  def initialize(title, pages)
    @title = title
    @pages = pages
  end
end

book = Book.new("Dune", 412)
puts book.title
puts book.pages

Output:

Dune
412

attr_writer :title generates a setter, the method title=, which stores its argument in @title. Ruby lets you call it with assignment syntax, book.title = "Emma":

class Book
  attr_reader :title
  attr_writer :title

  def initialize(title)
    @title = title
  end
end

book = Book.new("Dune")
book.title = "Dune Messiah"
puts book.title

Output:

Dune Messiah

attr_accessor generates both the reader and the setter. With both in place, shorthand such as += works too, because player.score += 5 means player.score = player.score + 5:

class Player
  attr_accessor :name, :score

  def initialize(name)
    @name = name
    @score = 0
  end
end

ada = Player.new("Ada")
ada.score += 5
ada.score += 3
ada.name = "Ada L."
puts "#{ada.name}: #{ada.score}"

Output:

Ada L.: 8

Expose as little as you can. Use attr_reader for values that outside code may read but not change, and add a writer only where changing the value from outside is part of the design. Assigning to a reader-only attribute raises NoMethodError:

class Book
  attr_reader :title

  def initialize(title)
    @title = title
  end
end

book = Book.new("Dune")
begin
  book.title = "Emma"
rescue NoMethodError => e
  puts e.message
end
puts book.title

Output:

undefined method `title=' for an instance of Book
Dune
challenge icon

Challenge

Easy

Complete the class Book. Outside code can read title, author and pages, and it can read and change pages_read, which starts at 0. progress returns Dune: 120/412 (29%), with the percentage rounded down.

The supplied code creates a book from the first three input lines (title, author, pages). Every following line is a number of pages the reader got through; the code adds each with book.pages_read += n. Finally it prints Dune by Frank Herbert and the progress.

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

Try it yourself

require_relative 'book'

# Supplied input/output code: keep it as it is
input = []
while (line = gets)
  input << line.chomp
end
book = Book.new(input[0], input[1], input[2].to_i)
input.drop(3).each { |n| book.pages_read += n.to_i }
puts "#{book.title} by #{book.author}"
puts book.progress
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