Inheritance in Java

Inheritance is one of the fundamental attributes of object-oriented programming. It allows you to define a child class that reuses (inherits), extends, or modifies the behavior of a parent class. The class whose members are inherited is called the base class. The class that inherits the members of the base class is called the subclass.

OOP UML Inheritance & Polymorphism.png

Inheritance in Polygon as Base Class

Inheritance Modifiers

Java introduces the following class-level statements and modifiers to support inheritance:

  • extends statement is used to declare a new class, called a subclass, based on an existing class, known as a base class.
  • final statement is to prevents programmers from using the class as a base class.
  • abstract statement specifies that the class is intended for use as a base class only. Instances of abstract classes cannot be created directly; they can only be created as base class of a subclass.

The following section describes some of the rules for inheritance, and the modifiers you can use to change the way classes inherit or are inherited:

  • By default, all classes are inheritable unless marked with the final keyword.
  • Java support single inheritance only. That is, a class can only inherit from a single class. However, inheritance is transitive, which allows you to define an inheritance hierarchy for a set of types. In other words, type D can inherit from type C, which inherits from type B, which inherits from the base class type A. Because inheritance is transitive, the members of type A are available to type D.

Overriding Methods in Subclasses

By default, a subclass inherits methods from its base class. If an inherited method has to behave differently in the subclass it can be overridden. That is, you can define a new implementation of the method in the subclass. The following annotation and modifiers are used to control how methods are overridden:

  • @Override will overrides an overridable method defined in the base class. @Override is optional in Java. All it does is validate that a base class method with the same signature exists. It doesn't work in the other direction.
  • final statement prevents a method from being overridden in an inheriting class.
  • abstract statement requires that a derived class override the method. When the abstract keyword is used, the method is declared without an implementation (without braces, and followed by a semicolon) . If a class includes abstract methods, then the class itself must be declared abstract.

Following is an example demonstrating Java inheritance. In this example, you can observe two classes namely BaseClass and SubClass.

BaseClass .java
import java.math.BigDecimal;

public class BaseClass {
    
    public BigDecimal calculatePayment(int number, BigDecimal price) {
        return new BigDecimal(number).multiply(price);
    }
    
    public String settlePayment(BigDecimal payment) {
        return payment.setScale(2, BigDecimal.ROUND_HALF_UP).toString() + " is settled";
    }
}
                    

SubClass.java
import java.math.BigDecimal;

public class SubClass extends BaseClass {
    
    @Override
    public BigDecimal calculatePayment(int number, BigDecimal price) {
        // Call the method in the base class and modify the return value. 
        return super.calculatePayment(number, price).multiply(new BigDecimal("2"));
    }
}
                    

Using extends keyword, the SubClass inherits the methods "calculatePayment" and "settlePayment" of BaseClass. Method calculatePayment(int number, BigDecimal price) is overrided in SubClass.

And below is an example demonstrating Java final class. When a subclass extends from Final, it will throw compilation error: cannot inherit from final FinalClass

FinalClass.java
public final class FinalClass {
 
    public String finalSay() {
        return "I'm final";
    }
}
                    

The super Keyword

You can use the super keyword to call methods in a base class when you override methods in a subclass. For example, suppose you are designing a subclass that overrides a method inherited from the base class. The overridden method can call the method in the base class and modify the return value as shown in SubClass.java above.

The following list describes restrictions on using super:

  • super refers to the immediate base class and its inherited members. It cannot be used to access private members in the class.
  • super is a keyword, not a real object. super cannot be assigned to a variable, passed to functions, or used in an Is comparison.
  • The method that super qualifies does not have to be defined in the immediate base class; it may instead be defined in an indirectly inherited base class. In order for a reference qualified by super to compile correctly, some base class must contain a method matching the name and the parameters in the call.
  • You cannot use super to call an abstract base class methods (This is no brainer).
  • super cannot be used to qualify itself. Therefore, the following code is not valid:
    super.super.doSomething();
  • MyBase cannot be used to access base class members that are marked as private.

When Do We Use Inheritance?

Inheritance is a useful programming concept, but it is easy to use inappropriately. Often interfaces do the job better. When to Use Interfaces help you understand when each approach should be used.

Inheritance is a good choice when:

  • Your inheritance hierarchy represents an "is-a" relationship and not a "has-a" relationship.
  • You can reuse code from the base classes.
  • You need to apply the same class and methods to different data types.
  • The class hierarchy is reasonably shallow, and other developers are not likely to add many more levels.
  • You want to make global changes to derived classes by changing a base class.