-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Methods and Blocks
-
Section 4: Object-Oriented Ruby
-
Section 5: Metaprogramming
-
Section 6: Working with Data and Files
-
Section 7: Ruby Frameworks Overview
-
Section 8: Ecosystem and Testing
-
Section 9: Practical Projects
-
Section 10: Interview Practice
-
Section 11: Data Structures and Algorithms in Ruby
-
Section 12: More Practice Exercises
-
Section 13: Enumerable and Functional Style
-
Section 14: More OOP Practice
-
Section 15: More Testing
-
Section 16: Enumerable and Comparable Modules In Depth
-
Section 17: Ruby Standard Library: Core Utilities
-
Section 18: Ruby Standard Library: Data and Security
-
Section 19: Ruby Standard Library: CLI and Text
-
Section 20: Ruby Networking
-
Section 21: Ruby on Rails Deep Dive
-
Section 22: Ruby Metaprogramming Deep Dive
-
Section 23: Ruby Design Patterns
-
Section 24: Ruby Concurrency
-
Section 25: Ruby Testing Deep Dive
-
Section 26: Ruby Gems and Packaging
-
Section 27: Ruby Performance
-
Section 28: More Practice Exercises
-
Section 29: More Interview Practice
-
Section 30: Rails API Development
-
Section 31: Rails Authentication and Authorization
-
Section 32: Rails Testing Deep Dive
-
Section 33: Rails Performance
-
Section 34: Rails Deployment
-
Section 35: Sinatra and Lightweight Ruby Web Apps
-
Section 36: More Ruby Language Deep Dive
-
Section 37: Ruby 3.x Modern Features
-
Section 38: More Data Structures in Ruby
-
Section 39: More Practical Projects
-
Section 40: Ruby Ecosystem Tools
-
Section 41: More Practice and Review
-
Section 42: Final Practice and Mastery
-
Section 43: Ruby Interview Deep Dive
-
Section 44: Ruby Background Processing Deep Dive
-
Section 45: Ruby GraphQL
-
Section 46: Ruby Object Model Deep Dive
-
Section 47: Ruby Hanami Framework Overview
-
Section 48: Ruby gRPC and Protocol Buffers
-
Section 49: Ruby Data Processing
-
Section 50: Ruby Search Integration
-
Section 51: Ruby File Upload and Media
-
Section 52: Ruby Email and Notifications
-
Section 53: Ruby Admin Panels
-
Section 54: Ruby Feature Flags and Experimentation
-
Section 55: Ruby Monitoring and Observability
-
Section 56: Ruby Docker and Deployment Deep Dive
-
Section 57: Ruby Security Deep Dive
-
Section 58: More Advanced Metaprogramming
-
Section 59: More Final Projects
51: Practice Exercise: Building a Class Hierarchy for a Zoo Simulation
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
Animalwithnameandspeciesattributes. - Create three subclasses:
Mammal,Bird, andReptile. Each should have a unique method (e.g.,Mammalhasfur_color,Birdhaswing_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_soundmethod inherited fromAnimal. - The Challenge: Create a
Habitatclass. It should have a name (like "The Savannah") and an array called@residents. Implement a methodwake_up_animalsthat iterates through all residents and calls theirmake_soundmethod.
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!
There are no comments for now.