Skip to Content
Course content

41: Practice Exercise: Building an Employee Management Hierarchy

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

Think about how a company organogram actually works. At the most basic level, everyone in the building is an "Employee." Whether they're the CEO or the junior intern, they all have a name, an employee ID, and they all get paid. However, the way they get paid or the specific responsibilities they have vary wildly. You wouldn't want to create a completely separate system for every single job title—that would be a maintenance nightmare. Instead, you define the "Employee" basics once and then layer the specifics on top.

In Java, this is where inheritance and polymorphism stop being abstract concepts and start becoming your best friends. We're going to map that corporate structure directly into our code:

  • The Base Class (Employee): This is our "general template." It holds the fields that everyone shares, like name and id.
  • The Subclasses (Manager, Developer): These are the specializations. A Manager "is-an" Employee, but they also have a teamSize. A Developer "is-an" Employee, but they have a programmingLanguage.
  • Method Overriding: Everyone gets a paycheck, but a Manager might get a bonus based on team performance, while a Developer gets a flat salary. We define a calculatePay() method in the base class, but we override it in the subclasses to handle the specific math.
  • Polymorphism: This is the magic part. It allows us to keep a List<Employee> that contains both Managers and Developers. When we loop through that list and call calculatePay(), Java is smart enough to call the Manager's version for managers and the Developer's version for developers.

Defining the Core Identity

I always recommend starting with the most generic class first. If you find yourself putting "manager-specific" logic in the base Employee class, stop. The base class should only contain what is universally true for every single person in the hierarchy. Use protected modifiers for fields you want subclasses to access directly without needing public getters for everything.

public class Employee {
    protected String name;
    protected int id;

    public Employee(String name, int id) {
        this.name = name;
        this.id = id;
    }

    public double calculatePay() {
        return 3000.0; // Base pay for any employee
    }

    public void displayDetails() {
        System.out.println("ID: " + id + ", Name: " + name);
    }
}

Adding the Specializations

When we create the Manager class, we use the extends keyword. Notice the use of super() in the constructor. I see a lot of beginners forget this or try to re-assign the name and ID manually. Don't do that. Let the parent class handle the initialization of its own fields; your subclass should only care about its own unique data.

public class Manager extends Employee {
    private double bonus;

    public Manager(String name, int id, double bonus) {
        super(name, id); // Pass the basics up to the Employee constructor
        this.bonus = bonus;
    }

    @Override
    public double calculatePay() {
        // Managers get base pay plus their specific bonus
        return super.calculatePay() + bonus;
    }
}

Handling the Hierarchy as a Group

The real power comes when you stop treating these as separate types. If you're writing a payroll system, you don't want a processManagerPay() method and a processDeveloperPay() method. You want one method that handles Employee objects. This keeps your code clean and means that if you add a Consultant class later, you don't have to change your payroll logic at all.

List<Employee> staff = new ArrayList<>();
staff.add(new Manager("Alice", 101, 500.0));
staff.add(new Developer("Bob", 102, "Java"));

for (Employee e : staff) {
    // Java decides at runtime which calculatePay() to use
    System.out.println(e.name + " earns: " + e.calculatePay());
}



📋 Practical Task

Building the Corporate Payroll System

Your task is to implement a functional employee hierarchy that handles different payment structures for different types of workers. This will test your ability to use inheritance, constructor chaining with super(), and polymorphic method calls.

Requirements:

  • Create a base class Employee with fields for name (String) and baseSalary (double). Include a method double getPayment() that simply returns the baseSalary.
  • Create a subclass FullTimeEmployee that adds a bonus field. Override getPayment() to return the base salary plus the bonus.
  • Create a subclass Contractor that replaces the base salary logic. Instead of a salary, they have an hourlyRate (double) and hoursWorked (int). Override getPayment() to return hourlyRate * hoursWorked.
  • In a Main class, create an ArrayList<Employee>. Add at least one FullTimeEmployee and one Contractor to this list.
  • Loop through the list and print the name and the calculated payment for each person. Ensure that the correct payment logic is applied based on the object's actual type.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.