Hubert Jakubiak
Hubert Jakubiak

Reputation: 1013

Why this instance variable is not incrementing?

This short code is working when I'm using class variable @@points instead of @points. I wonder why it's happening like this? Someone can explain me? It looks like @points is always nil.

class Game

  @points = 0

  def start

    until @points == 10
      puts "Guess number between 0 and 10:" 
      num = gets.chomp.to_i
      break if @points == 0
      guess_number(num)
      puts "Your score is: #{@points}"

    end

  end

  def guess_number(num)
    @points += 1 if num == rand(0..10)
  end

end

game = Game.new
game.start

Upvotes: 1

Views: 260

Answers (2)

Hubert Jakubiak
Hubert Jakubiak

Reputation: 1013

Thanks to answer by Andrey Deineko. I came up with such solution to use instance variable here.

class Game

  def initialize
    @points = 0
  end

  def start

    until points == 10
      puts "Guess number between 0 and 10:" 
      num = gets.chomp.to_i
      break if points == 10
      guess_number(num)
      puts "Your score is: #{points}"

    end

  end

  private

  def guess_number(num)
    if num == rand(0..10)
      increment_points
    end
  end

  def points
    @points
  end

  def increment_points
    @points += 1
  end

end

game = Game.new
game.start

Upvotes: 0

Andrey Deineko
Andrey Deineko

Reputation: 52377

Because @points is a class instance variable, and to access it from within the instance method's scope you'd have to either do

self.class.instance_variable_get(:@points)

or define an attr_accessor in Game's singleton_class

class Game; class << self; attr_accessor :points; end; end

and then you'd be able to do

self.class.points

But neither of these is what you really want.

code is working when I'm using class variable @@points instead of @points

It is working, because you do have access to class variable from within a scope of an instance methods.

It looks like @points is always nil

It is always nil, because you never defined an instance variable @points, but, as said, class instance variable.

So these three things are different (you could read up something about Ruby scoping - do not mix with AR scopes):

  • class variable
  • class instance variable
  • instance variable

To solve it there are many ways, but if you want to keep it on the instance level, wrap @points into a method:

def points
  @points ||= 0
end

And then use it as points - now it'll work as you are expecting.

Upvotes: 2

Related Questions