rubyclass-instance-variables

class instance variables proper usage


class variable works like this:

class Hello
  @@x = 0

  def self.counter
   @@x
  end

  def initialize
    @@x += 1
  end  
end

Hello.new
Hello.new
Hello.new
p Hello.counter
#=> 3

but class instance variable doesn't:

class Goodbye
  @x = 0

  def self.counter
   @x
  end

  def initialize
    @x += 1
  end  
end

Goodbye.new
Goodbye.new
Goodbye.new
Goodbye.new
p Goodbye.counter
#=> Error

What am I doing wrong ? I was under impression that class instance variables are same as class variables, just without inheritance problem ... but how do you use them (for example, to count instances of specific class like in code I posted here) ?


Solution

  • Instance variables belong to objects (instances), that's why they are called that. In lines 2 and 5, @x belongs to the object Goodbye, but in line 9, @x belongs to an instance of Goodbye. You never initialize this instance variable, and uninitialized instance variables evaluate to nil, nil doesn't have a + method, ergo you get a NoMethodError.

    Note that Goodbye.counter does not raise an error like you claim, it simply returns 0. The error is raised inside initialize.

    Here's the trivial fix:

    class Goodbye
      @x = 0
    
      def self.counter
       @x
      end
    
      def self.new
        @x += 1
        super
      end  
    end
    
    Goodbye.new
    Goodbye.new
    Goodbye.new
    Goodbye.new
    p Goodbye.counter
    #=> 4