Exercise Overview

How to Use These Exercises

These exercises are designed to reinforce your understanding of Java inheritance and polymorphism including class hierarchies, method overriding, abstract classes, interfaces, and polymorphic behavior. Start with the easy exercises and progress to more challenging ones as you build confidence.

Tips for Success:

  • Understand the relationship between base and derived classes
  • Practice method overriding with @Override annotation
  • Learn to use abstract classes and interfaces effectively
  • Master polymorphic behavior and dynamic binding
  • Follow inheritance design principles
3 Easy Exercises
3 Medium Exercises
2 Hard Exercises

Easy Exercises - Start Here!

5.1

Basic Inheritance

Easy

Create a simple inheritance hierarchy with a base class and derived class.

Requirements:

  • Create a base class called Animal with attributes: name, age
  • Create a derived class called Dog that extends Animal
  • Add a breed attribute to Dog
  • Create constructors for both classes
  • Override the toString() method in Dog
  • Test the inheritance relationship

Expected Output:

Animal: Buddy, Age: 3
Dog: Buddy, Age: 3, Breed: Golden Retriever

Animal: Whiskers, Age: 2
Dog: Max, Age: 5, Breed: German Shepherd

Hints:

  • Use extends keyword to create inheritance
  • Use super() to call parent constructor
  • Use protected for attributes accessible by subclasses
  • Override toString() to provide meaningful output
  • Test with both Animal and Dog objects
5.2

Method Overriding

Easy

Practice method overriding with the @Override annotation.

Requirements:

  • Add a makeSound() method to Animal class
  • Override makeSound() in Dog class to return "Woof!"
  • Create a Cat class that extends Animal
  • Override makeSound() in Cat to return "Meow!"
  • Use @Override annotation for all overridden methods
  • Test all three classes

Expected Output:

Animal sound: Some animal sound
Dog sound: Woof!
Cat sound: Meow!

Testing polymorphic behavior:
Animal (Dog): Woof!
Animal (Cat): Meow!

Hints:

  • Use @Override annotation for clarity
  • Method signature must match exactly (name, parameters, return type)
  • Access modifier can be the same or more accessible
  • Test with both direct calls and polymorphic calls
  • Use super.makeSound() if you want to call parent method
5.3

Polymorphism

Easy

Demonstrate polymorphism using method overriding and dynamic binding.

Requirements:

  • Create an array of Animal objects containing different animal types
  • Loop through the array and call makeSound() on each animal
  • Demonstrate that the correct sound is produced for each animal type
  • Create a method that accepts an Animal parameter and calls makeSound()
  • Show polymorphic behavior with different animal types

Expected Output:

Polymorphic behavior demonstration:
Woof!
Meow!
Woof!

Using method with Animal parameter:
Animal 1: Woof!
Animal 2: Meow!
Animal 3: Woof!

Hints:

  • Use Animal[] to store different animal types
  • Dynamic binding occurs at runtime based on actual object type
  • Same method call produces different results based on object type
  • Use enhanced for loop to iterate through array
  • Create a helper method to demonstrate polymorphic calls

Medium Exercises - Build Your Skills!

5.4

Abstract Classes

Medium

Create and use abstract classes to define common behavior.

Requirements:

  • Make Animal class abstract
  • Add an abstract method getSpecies() to Animal
  • Implement getSpecies() in Dog and Cat classes
  • Create another abstract method getHabitat()
  • Demonstrate that you cannot instantiate Animal directly
  • Add concrete methods to abstract class

Expected Output:

Dog species: Canis familiaris
Dog habitat: Domestic
Cat species: Felis catus
Cat habitat: Domestic

Trying to create Animal directly:
Error: Cannot instantiate abstract class Animal

Hints:

  • Use abstract keyword for class and methods
  • Abstract methods have no implementation in parent class
  • Concrete methods can exist alongside abstract methods
  • Subclasses must implement all abstract methods
  • Abstract classes cannot be instantiated directly
5.5

Interfaces

Medium

Create and implement interfaces to define contracts.

Requirements:

  • Create an interface called Playable with method play()
  • Create an interface called Trainable with method train()
  • Implement both interfaces in Dog class
  • Implement only Playable in Cat class
  • Demonstrate interface usage with different animal types
  • Use interface as parameter type

Expected Output:

Dog is playing fetch
Dog is being trained to sit
Cat is playing with yarn

Testing with interface parameter:
Playable animal: Dog is playing fetch
Playable animal: Cat is playing with yarn

Hints:

  • Use interface keyword to define interfaces
  • Use implements keyword to implement interfaces
  • Interfaces can have multiple implementations
  • Classes can implement multiple interfaces
  • Use interfaces as parameter types for flexibility
5.6

Method Overloading vs Overriding

Medium

Understand the difference between method overloading and overriding.

Requirements:

  • Create overloaded methods in Animal class (different parameters)
  • Override methods in subclasses (same signature)
  • Demonstrate both overloading and overriding in same class
  • Show how Java chooses between overloaded methods
  • Compare compile-time vs runtime binding

Expected Output:

Overloading examples:
Animal: makeSound() - Some animal sound
Animal: makeSound(3) - Some animal sound repeated 3 times

Overriding examples:
Dog: makeSound() - Woof!
Cat: makeSound() - Meow!

Combined demonstration:
Dog: makeSound() - Woof!
Dog: makeSound(2) - Woof! Woof!

Hints:

  • Overloading: same name, different parameters (compile-time)
  • Overriding: same signature, different implementation (runtime)
  • Overloading can exist in same class or inheritance hierarchy
  • Overriding only exists in inheritance hierarchy
  • Use @Override annotation for clarity

Hard Exercises - Master the Concepts!

5.7

Complex Inheritance Hierarchy

Hard

Create a complex inheritance hierarchy with multiple levels.

Requirements:

  • Create a hierarchy: Animal → Mammal → Dog/Cat → SpecificBreeds
  • Add appropriate attributes and methods at each level
  • Use method overriding at multiple levels
  • Implement interfaces at different levels
  • Demonstrate polymorphic behavior throughout hierarchy
  • Create utility methods that work with any level

Expected Output:

Hierarchy demonstration:
Golden Retriever: Canis familiaris (Mammal)
- Sound: Woof!
- Habitat: Domestic
- Breed: Golden Retriever
- Training: Advanced

Persian Cat: Felis catus (Mammal)
- Sound: Meow!
- Habitat: Domestic
- Breed: Persian
- Play: Loves yarn

Hints:

  • Plan the hierarchy carefully before implementation
  • Use super() to call parent constructors
  • Consider which methods should be abstract vs concrete
  • Use interfaces for cross-cutting concerns
  • Test polymorphic behavior at each level
5.8

Design Patterns with Inheritance

Hard

Implement common design patterns using inheritance and polymorphism.

Requirements:

  • Implement Factory Pattern for creating different animal types
  • Implement Strategy Pattern for different behaviors
  • Implement Template Method Pattern with abstract classes
  • Create a registry system for animal types
  • Demonstrate runtime type checking and casting
  • Add reflection capabilities for dynamic behavior

Expected Output:

Factory Pattern:
Created: Dog (Golden Retriever)
Created: Cat (Persian)

Strategy Pattern:
Dog behavior: Aggressive
Cat behavior: Calm

Template Method:
Animal lifecycle: Born → Grow → Reproduce → Die

Registry System:
Registered animals: Dog, Cat, Bird
Available types: [Dog, Cat, Bird]

Hints:

  • Factory Pattern: centralize object creation
  • Strategy Pattern: encapsulate algorithms
  • Template Method: define algorithm skeleton
  • Use instanceof for type checking
  • Use Class.forName() for reflection

🎉 Module 5 Exercises Complete!

You've practiced Java inheritance and polymorphism including class hierarchies, method overriding, abstract classes, and interfaces. Ready to move on to arrays and collections!