Menu
Coddy logo textTech

Class Instance Variables

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

A class is an object too, so it can have its own instance variables. @issued = 0 in the class body, where self is the class, belongs to the class and not to any instance. Class methods read and change it:

class Ticket
  @issued = 0

  def self.issue
    @issued += 1
  end

  def self.issued
    @issued
  end
end

Ticket.issue
Ticket.issue
puts Ticket.issued

Output:

2

attr_accessor inside class << self generates a reader and setter on the class. Instances then reach the class's state through self.class, for example to count every object that new creates:

class Robot
  @built = 0

  class << self
    attr_accessor :built
  end

  attr_reader :serial

  def initialize
    self.class.built += 1
    @serial = self.class.built
  end
end

a = Robot.new
b = Robot.new
puts "#{a.serial} #{b.serial} #{Robot.built}"

Output:

1 2 2

Ruby also has class variables, written @@name. A class variable is shared by the class and all of its instances, so instance methods can read it directly:

class Player
  @@count = 0

  def initialize
    @@count += 1
  end

  def self.count
    @@count
  end

  def others
    @@count - 1
  end
end

Player.new
last = Player.new
puts Player.count
puts last.others

Output:

2
1

A class variable is also shared with every subclass (a class built on another one, chapter 5), so a subclass that assigns it changes it for the parent too. A class instance variable stays separate per class, which is why most Ruby code prefers it:

class Base
  @@kind = "base"
  @label = "base"

  class << self
    attr_reader :label
  end

  def self.kind
    @@kind
  end
end

class Child < Base
  @@kind = "child"
  @label = "child"
end

puts Base.kind
puts Base.label
puts Child.label

Output:

child
base
child
challenge icon

Challenge

Easy

Complete the class Ticket. Every new ticket gets the next number, starting at 1, from a counter kept in a class instance variable. Ticket.issued returns how many tickets have been issued since the last reset, and Ticket.reset sets the counter back to 0. to_s returns #3 Concert.

The supplied code reads lines. reset resets the counter; any other line is an event name, for which it creates a ticket and prints it. At the end it prints issued: 2.

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

Try it yourself

require_relative 'ticket'

# Supplied input/output code: keep it as it is
input = []
while (line = gets)
  input << line.chomp
end
input.each do |line|
  if line == "reset"
    Ticket.reset
  else
    puts Ticket.new(line)
  end
end
puts "issued: #{Ticket.issued}"
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