0

I'm trying to get the following code to work.

class Animal

end

class Tiger < Animal
    @hunger = 100

    def self.hunger
        @hunger 
    end

    def run
        puts "The Tiger runs"
        @hunger += 10
    end
end

class Statistics
    puts "This tigers hunger is: #{Tiger.hunger}" 
end

tiger = Tiger.new()
tiger.run

So the tiger has a variable called hunger which is by itself at the top of the Tiger class. I want to make it so this variable can be changed throughout the class methods. For example in run the hunger is set to hunger += 10, but when I run this code I get an undefined method '+' for nil:NilClass (NoMethodError). What do I do to make this program work so the variable can be changed and then displayed in the Statistics class?

3 Answers 3

2

The problem is that you have completely mushed class and instance variables/methods together.

If you want to use instances (which you should):

class Animal; end

class Tiger < Animal
  attr_reader :hunger

  def initialize
    @hunger = 100
  end

  def run
    puts "The Tiger runs"
    @hunger += 10
  end
end

class Statistics
  def self.show(tiger)
    puts "This tigers hunger is: #{tiger.hunger}" 
  end
end

tiger = Tiger.new
tiger.run
Statistics.show(tiger)

If you want to use class methods/variables:

class Animal; end

class Tiger < Animal
  @hunger = 100

  def self.hunger
    @hunger
  end

  def self.run
    puts "The Tiger runs"
    @hunger += 10
  end
end

class Statistics
  def self.show
    puts "This tigers hunger is: #{Tiger.hunger}" 
  end
end

Tiger.run
Statistics.show

Note that @hunger is now a class instance variable of Tiger. The difference between class instance variables and class variables (ones defined with @@) is that the latter is shared by all descendants of the said class, while the former is only tied to the class where it was defined.

I do not agree with your descision about Statistic in either case though.

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you! It seems to work on the sample code so I'll see if I can incorporate it into my bigger project.
Since the OP has a class instance variable (and an instance variable with the same name), and also because class instance variables are generally a better choice than class variables, you might want to say something about the former.
@CarySwoveland, good point. By the way OP is creating his hierarchy, I was definitely about to make him hit a brick wall.
@ndn thanks for the update and explanation. I'm going to try out a few of the answers and see what works, then I'll select a best answer. One thing I'm curious about though. What if I only plan to have a single instance of Tiger? Wouldn't it kind of make sense to use @@ or no?
@JamesMitchell, if you have a single instance of tiger, you should define an instance and not use class variables/methods. But if you mean that you will treat the Tiger class as a single entity - as long as you don't subclass it and the super classes (Animal) don't have it, @@ will be fine. Class variables are weird.
1

Don't you need an initialize method in your Tiger class?

def initialize()
@hunger = 100
end

I am confused about your Statistics class. Shouldn't this be a method in the Tiger class? How does it know what Tiger to access? I would add that puts in a method taking your tiger as a parameter if you want to do that.

class Statistics
def tiger_stat(tiger_name)
puts "This tigers hunger is: #{tiger_name.hunger}" 
end
end

Edit* this is the code I would use:

class Animal
    def initialize(animal_type, hunger_start)
        @animal_type = animal_type
        @hunger = hunger_start
    end

    def hunger_print
        puts "This #{@animal_type}'s hunger is: #{@hunger}."
    end
end

class Tiger < Animal
    def initialize
        super("Tiger", 100)
    end

    def run
        puts "The Tiger runs"
        @hunger += 10
    end
end

This way you can call hunger_print on any animal without worrying about the type or making an extra class. You could do something like.

tiger = Tiger.new
tiger.run
tiger.hunger_print

2 Comments

All the code I have here is just a sample for a bigger project. I have the stats class because really I have 3 animal classes and then the stats would compare the hunger of all the animals. I tried the initialize and it doesn't work.
Oh I understand. I would recommend using inheritance if you want to do something like that. Are you familiar with the concept?
0

You can use class variable that is access from both instance and class methods.

class Animal
  @@hunger = 100

  def self.hunger
    @@hunger
  end

  def self.increase_hunger
    @@hunger +=1
  end

  def hunger
    @@hunger
  end

  def increase_hunger
    @@hunger += 1
  end
end

Animal.increase_hunger
puts Animal.hunger # => 101
animal = Animal.new
animal.increase_hunger
puts animal.hunger # => 102

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.