Skip to Content
Course content

51: Practice Exercise: Building a Class Hierarchy for a Zoo Simulation

Click on the "Edit" button in the top corner of the screen to edit your slide content.

How do I actually structure these layers so it doesn't get confusing?

When you're building a simulation like this, the temptation is to just create a bunch of flat classes—Lion, Tiger, Eagle—all inheriting directly from Animal. But that's a missed opportunity. I usually suggest a "middle layer" for categories. Think of it as a way to group shared behaviors that aren't universal to every animal, but are true for a whole group.

For our zoo, I'd set it up like this: Animal (the grandparent) → Mammal (the parent) → Lion (the child). This way, if you decide all mammals need a give_birth method, you only write it once in the Mammal class instead of copying it into ten different species. Here is how that looks in code:

class Animal
  attr_reader :name
  def initialize(name)
    @name = name
  end

  def eat
    puts "#{@name} is eating some food."
  end
end

class Mammal < Animal
  def breathe
    puts "#{@name} is breathing air."
  end
end

class Lion < Mammal
  def roar
    puts "#{@name} lets out a massive roar!"
  end
end

Should I put the 'sound' method in the base class or only in the specific animals?

This is a classic design question. If you know every single animal in your zoo will make a sound, put the method in the base Animal class. However, don't give it a "real" implementation there. Instead, I like to make the base method raise an error or print a generic message. This forces you (or your teammates) to override it in the subclasses.

I call this "defining the interface." By putting make_sound in Animal, you can have a list of 100 random animals and call .make_sound on all of them without worrying if a specific animal forgot to implement it. Check out how I use super here to keep the base behavior while adding something specific:

class Animal
  def make_sound
    "Generic animal noise"
  end
end

class Dog < Animal
  def make_sound
    # I'm calling super to get the base string, then adding to it
    "#{super} ... but specifically, a Bark!"
  end
end

How do I deal with the 'special cases' where a subclass breaks the rule?

In a zoo simulation, you'll eventually hit a wall. For example: you decide all Bird classes have a fly method. Then you add a Penguin. Now you've got a penguin that can fly, which is a problem for your simulation's realism.

Don't try to over-engineer the hierarchy to avoid this. Just override the method in the specific subclass to reflect the reality of that animal. It's much cleaner to have a Penguin that explicitly says "I can't fly" than to create a complex FlightlessBird middle-class just for one or two animals. I've seen developers spend hours building "perfect" trees only to realize that nature is too messy for a perfect tree.

class Bird < Animal
  def move
    puts "#{@name} is flying through the air!"
  end
end

class Penguin < Bird
  def move
    puts "#{@name} is waddling on the ice!"
  end
end



📋 Practical Task

Exercise: Implementing the Zoo Habitat Management System

Now it's your turn to put this hierarchy into practice. You need to build a system that manages animals within specific habitats.

  • Create a base class Animal with name and species attributes.
  • Create three subclasses: Mammal, Bird, and Reptile. Each should have a unique method (e.g., Mammal has fur_color, Bird has wing_span).
  • Create at least one specific animal class for each (e.g., Elephant < Mammal, Parrot < Bird, Snake < Reptile).
  • Every specific animal must override a make_sound method inherited from Animal.
  • The Challenge: Create a Habitat class. It should have a name (like "The Savannah") and an array called @residents. Implement a method wake_up_animals that iterates through all residents and calls their make_sound method.

Test your code by adding a Lion, a Parrot, and a Snake to a single Habitat and calling wake_up_animals to ensure the polymorphism is working correctly!

Rating
0 0

There are no comments for now.

to be the first to leave a comment.