sayth
sayth

Reputation: 7048

Classes Error in Ruby - NoMethod

Following on from the Grandma question here i wanted to take their advice and inplement the counter as a class. Deaf Grandma

This is where I am at

puts 'Say something nice to Grandma.'
puts 'You may need to shout > '

class Counter
  counter = 0
  def Plus
    counter += 1
  end
  def Minus
    counter -= 1
  end
  def Reset
    counter = 0
  end
end

MyCounter = Counter.new

def speaks()
    $speak = gets.strip
    if $speak != 'Bye'
        talk()
    else
        exitPlan()
    end
end

def talk()
    if $speak == $speak.downcase
        puts 'Huh Speak up Sonny'
    else
        year = rand(1930..1951)
        puts 'No not Since ' + year.to_s
    end
        MyCounter.Minus
        if counter < 0
            Counter.reset
        end
        puts 'Say something nice to Grandma'
        speaks()
end

def exitPlan()
    MyCounter.Plus
    unless counter == 3
        puts 'Say something nice to Grandma'
        speaks()
    else
        puts 'good night Sonny'
    end
end
speaks()

This is the NoMethod Error

C:\Users\renshaw family\Documents\Ruby>ruby gran2.rb
Say something nice to Grandma.
You may need to shout >
Hi
No not Since 1939
gran2.rb:10:in `Minus': undefined method `-' for nil:NilClass (NoMethodError)
        from gran2.rb:35:in `talk'
        from gran2.rb:22:in `speaks'
        from gran2.rb:52:in `<main>'

Upvotes: 0

Views: 282

Answers (1)

Andrew Marshall
Andrew Marshall

Reputation: 97004

When you do the following:

class Counter
  counter = 0
end

counter is a local variable and disappears when you exit the class definition, this means that it does not exist at any time later on, and thus counter is nil and you are trying to call - on it (nil) when doing counter -= 1, which results in NoMethodError. What you seem to be trying to do is initialize an instance variable during instantiation:

class Counter
  def initialize
    @counter = 0
  end

  def plus
    @counter += 1
  end

  def minus
    @counter -= 1
  end

  def reset
    @counter = 0
  end
end

The initialize method is the name for the constructor in Ruby, and is called when you call Counter.new. Also note that I have changed the method names to begin with a lowercase letter, as is convention: classnames are capitalized, methods and variables are lowercase.

I would also highly discourage using global variables (e.g. $speak).

Upvotes: 3

Related Questions