Method Overriding in Java

This post is Part 5 of Inheritance in Java series of articles. The series explains inheritance in Java in detail. This part explains method overriding and its relation with inheritance. It is suggested you first read the basics of inheritance which is explained in Part 1 to Part 4.

When we inherit a class from another class, its methods and attributes are inherited based on their access modifiers. Method overriding is a concept of redefining an inherited method in the child class. When we redefine a method in child class to override; its name, list of arguments with order and types should be same as defined in the parent class. The return type in the child class must be same as, or a subtype of, the return type defined in parent class. After overriding, when we create an object of child class and call the overridden method, the method of child class would be executed instead of parent class. Lets see it working using in Shape and Rectangle classes.

package com.bitspedia;

public class Shape {
    public int calculateArea() {
        System.out.println("calculateArea method is called of class Shape.");
        return 0;
    }
}

Lets override calculateArea method in Rectangle class.

package com.bitspedia;

public class Rectangle extends Shape {
    private int width;
    private int length;

    public Rectangle(int width, int length) {
        this.width = width;
        this.length = length;
    }

    @Override
    public int calculateArea() {
        System.out.println("calculateArea called of class Rectangle.");
        int area = width * length;
        return area;
    }
}

Now we make an object of child class i.e. Rectangle and call the overriden method.

package com.bitspedia;

public class Test {    

    public static void main(String[] args) {
        Rectangle rectangle = new Rectangle(3,4);
        System.out.println(rectangle.calculateArea());
    }
}

If you compile the Test class, you would notice the calculateArea inside the Rectangle class is called. If you do not override, the parent class i.e. Shape's calculateArea method would be called. Here is the output of above Test class:
calculateArea called of class Rectangle.
12


Using the Overridden Method in Child Class

Once we override a method, we can't call the parent class implementation from child class object e.g. from rectangle object defined in Test class above. Overridden methods can be called from inside the subclass. I would elaborate with the help of an example in a while. First understand, we encounter usually two cases of overriding:
  1. Changing the parent method implementation altogether. In this case we provide new implementation of earlier defined method in child class and do not call the parent class method. As explained in Shape/Rectangle example above. The Rectangle class provide completely new implementation of calculateArea method and do not call the calculateArea method of Shape class.
  2. Sometime we want to provide new implementation in child class that is an extension to parent class method. So in this case, we use the functionality of parent class method while defining the child class method.

Here I explain the 2nd case with the help of an example. Assume an organization gives basic salary to all employees. She hires two types of employees, those who work on hourly bases and those who work on commission base. In addition to basic salary, both employees get additional amount based on hours worked or sales commission. First I share code listing of Employee and HourlyEmployee classes.

package com.bitspedia;

public class Employee {
    private String name;
    private int basicSalary;

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

    public int getEarnings(){
        return basicSalary;
    }
}

package com.bitspedia;

public class HourlyEmployee extends Employee {
    private int hourlyRate;
    private int hoursWorked;

    public HourlyEmployee(String name, int basicSalary, int hourlyRate, int hoursWorked) {
        super(name, basicSalary);
        this.hourlyRate = hourlyRate;
        this.hoursWorked = hoursWorked;
    }

    @Override
    public int getEarnings() {
        return super.getEarnings() + (hoursWorked * hourlyRate);
    }
}

In above code listing, we called getEarnings method of parent class from the getEarnings method of child class. Though its very simple case, but good one to understand how the child class can provide the new implementation and still use the result of parent class method result. Such cases occurs when the implementation of child class depends on the result of parent class in one way or another. Just for the sake of completion, here I also provide the implementation of CommissionedEmployee and a EmployeeTest class with output.

package com.bitspedia;

public class CommissionedEmployee extends  Employee {

    private int totalSales;
    private float commissionRate; // in percent

    public CommissionedEmployee(String name, int basicSalary, int totalSales, float commissionRate) {
        super(name, basicSalary);
        this.totalSales = totalSales;
        this.commissionRate = commissionRate;
    }

    @Override
    public int getEarnings() {
        int totalCommission = (int) (totalSales * (commissionRate / 100)) ;
        // converted into int to keep it simple, in real app, it should be double

        return super.getEarnings() + totalCommission ;
    }
}

CommissionedEmployee class also overrides the getEarnings method. It provides its own logic to calculate employee's total earnings. No matter how much additional amount is added, it also get the basic salary from the super class getEarnigns method and adds more amount into it i.e. total commission. Here I share the EmployeeTest class code listing:

package com.bitspedia;

public class EmployeeTest {
  public static void main(String[] args) {
    HourlyEmployee hourlyEmployee = new HourlyEmployee("Alice", 50000, 30, 20);
    System.out.println("Total Earnings of Hourly Employee : " + hourlyEmployee.getEarnings());

    CommissionedEmployee commissionedEmployee = new CommissionedEmployee("Bob", 70000, 500000, 3);
    System.out.println("Total Earnings of Commissioned Employee : " + 
                                                            commissionedEmployee.getEarnings());
 }
}

Here is the output:
Total Earnings of Hourly Employee : 50600
Total Earnings of Commissioned Employee : 85000

A natural question here is, overriding does makes sense when we also use the parent class implementation in child class, as we saw getEarnings method in HourlyEmployee class above. But in the first case, when we completely override the parent method and do not call the functionality provided by parent class, then why we override instead removing the method from parent class and adding it only in child class. For example, why we do not skip calculateArea method altogether in Shape class and only add it into child class i.e. Rectangle, as it just returns 0 in Shape class, which does not makes much sense. The short answer to this question is, it helps us treating the objects of all child classes polymorphically. To understand this concept in more depth, you must know the polymorphism and abstraction concepts in Object Oriented Programming in great depth.

Comments

Post a Comment