This post was originally published on this site

Object-oriented programming (OOP) is a paradigm that models computer programs as a collection of objects that interact with one another. OOP differs from other programming approaches in its implementation of reusable code in the form of classes.

person usign inheritance in java on a laptop

To make this reusability possible, OOP-style programs use a mechanism called inheritance. The main idea behind inheritance is to create new classes (known as “child classes” or “children”) that inherit the attributes and methods of preexisting classes (known as “parent classes”) without the need to rewrite code.

Inheritance is an intuitive and useful tool for modeling the real world. For example, consider the concept of children inheriting certain physical attributes and behaviors from their parents. Inheritance is especially well-suited to model many such real-world phenomena.

Download Now: An Introduction to Java & JavaScript

For instance, imagine that you want to develop a game about penguins. For this, you’ll need a parent class — penguin — that specifies the attributes and methods that all child classes of penguin will have. You can then create these child classes with more unique attributes and methods, in addition to those already acquired from the more generic parent class. This eliminates the need to copy and paste code from the parent class into each child class.

For this reason, many programming languages implement OOP, including Java, the focus of this article. Java popularized the use of OOP in the 1980s by facilitating the implementation of the four core OOP principles: inheritance, encapsulation, abstraction, and polymorphism.

In this article, you’ll learn how inheritance works in Java, explore the five types of Java inheritance, and better understand how it works for representing real-world things in code.

Types of Inheritance in Java

Let’s now take a look at the various forms of inheritance and how they appear in Java programs.

Single Inheritance

Java uses the keyword extends to indicate that a Java class is inheriting attributes from another one. Inheritance means that the Penguin class will contain the grandParentMain method of the Animal class without having to rewrite it inside the Penguin class.

To understand single inheritance, in which the child class inherits from a single base class, consider the generic example below:



public class Animal {

protected String featherColor = "White";

public void setFeatherColor(String newColor) {
this.featherColor = newColor;
}
public void grandParentMain() {

System.out.println("This is the base class. It represents any animal.");
}
}

public class Penguin extends Animal {

String featherColor = "Black";

public void parentMain() {
System.out.println("The parentMain method returns a Penguin with " + featherColor + " feathers.");
}
}


You can easily test this idea by creating a simple program that instantiates a subclass and calls both methods (click the “output” tab to view the output of the code).



public class mainTest{

public static void main(String[] args) {

Penguin penguin = new Penguin();

penguin.grandParentMain();
penguin.parentMain();
}
}


This is the base class. It represents any animal.
The parentMain method returns a Penguin with Black feathers.

Using the code above, you can confirm the child class’s ability to use its parent’s methods.

Multilevel Inheritance

Multilevel inheritance occurs when one class inherits from a second class that already inherits from a third class.

To illustrate this concept, consider the two classes introduced in the previous section. You’ll now add a third class to describe a species within the Penguin class. This class will be called Emperor to represent an Emperor penguin. Because it inherits from Penguin, the Emperor class has access to all the attributes and methods of both the Penguin child class and the Animal base class.



public class Emperor extends Penguin {

int weight = 32; // kg
int height = 110; // cm

public void childMain() {

System.out.println("A special kind of penguin is called the Emperor penguin. It weighs about " + weight + " kg and measures around " + height + " cm tall.");
}
}

Adding this specificity requires adding new levels to the “object tree.” As the name suggests, this is multilevel inheritance.

The following code sample tests this concept by instantiating an Emperor object and demonstrating that it can access all three methods:



class mainTest{
public static void main(String[] args) {

Emperor emperor = new Emperor();

emperor.grandParentMain();
emperor.parentMain();
emperor.childMain();

}
}


This is the base class. It represents any animal.
The parentMain method returns a Penguin with Black feathers.
A special kind of penguin is called the Emperor penguin. It weighs about 32 kg and measures around 110 cm tall.

Hierarchical Inheritance

Suppose that you now want to add more species of penguins to your game to accompany the Emperor penguins. You’ll create a new class for Gentoo penguins, who are distinguished primarily by their orange beaks:



public class Gentoo extends Penguin {
String beakColor = "Orange";

public void dance() {
System.out.println("I have a(n) " + beakColor + " beak and love to dance.");
}
}

class mainTest{
public static void main(String[] args) {

Gentoo gentoo = new Gentoo();

gentoo.grandParentMain();
gentoo.parentMain();
gentoo.dance();
}
}


This is the base class. It represents any animal.
The parentMain method returns a Penguin with Black feathers.
I have a(n) Orange beak and love to dance.

As you can see, the Gentoo class inherits the same methods that Emperor does, but it adds a few customized attributes that characterize Gentoo penguins. Furthermore, since it isn’t inheriting from the Emperor class, trying to access the childMain method of the Emperor class will raise an error. This is called architecture hierarchical inheritance.

Multiple Inheritance

Multiple inheritance occurs when a single child class inherits from two parent classes. This style of inheritance is often very cumbersome and generates complicated problems. For example, the compiler is unable to distinguish or prioritize between two methods that have the same ID signature. For this reason, Java doesn’t support this type of multiple inheritance.

However, Java 8 presented an alternative — to implement multiple inheritance using Java interfaces and default methods. Interfaces are abstract classes that are often used to group related methods. This approach allows the implementing class to specify which method to use via a special keyword.

Furthermore, using default methods within interfaces helps to mitigate a common challenge of multiple inheritance: confusing the compiler. If two parents have a method with the same ID signature (meaning the function name), the compiler can’t determine which parent’s method to use. The Java keyword super allows the child class to access the methods of a specific parent class, therefore helping eliminate the ambiguity for the compiler.


-Escaped HTML-

interface Penguin1 {
default void show() {
System.out.println("I am Penguin1.");
}
}

interface Penguin2 {

default void show() {
System.out.println("I am Penguin2.");
}
}

class TestClass implements Penguin1, Penguin2 {

// Overriding default show method
public void show()
{
// Using super keyword for P1
Penguin1.super.show();

// Using super keyword for P2
Penguin2.super.show();
}

public static void main(String args[])
{
TestClass test = new TestClass();
test.show();
}
}


I am Penguin1
I am Penguin2

The example above uses an interface (instead of a class) to represent each parent. Both parents have a method with the same identifier: show. The TestClass class inherits from both parents.

To achieve multiple inheritance, you implement a third show method in the child class to override both methods. Then, using the keyword super, you specify which parent’s method you want to call. Therefore, you first call show from Penguin1 and then from Penguin2.

Hybrid Inheritance

For more flexibility, developers often combine two methods of inheritance. This practice is called hybrid inheritance. The goal of using hybrid inheritance is to modularize the codebase and develop well-defined classes.

Suppose you introduce a new class:



public class Catbird extends Animal{
public void show(){
System.out.println("I am a Catbird with " + featherColor + " feathers.");
}
}

You’ll then change the method names in your previous classes to show. You now have a hierarchical inheritance since both Penguin and Catbird inherit from Animal. You also have a multilevel inheritance because Gentoo inherits from Penguin.

This example also demonstrates the usage of protected members. Looking back at the Animal class, you used the keyword protect to restrict the accessibility of the featherColor attribute. This keyword makes it available only to methods within the class or those that inherit from it.



class mainTest{

public static void main(String[] args) {

Catbird catbird = new Catbird();

catbird.show();
catbird.setFeatherColor("Gray");
catbird.show();

}
}


I am a Catbird with White feathers.
I am a Catbird with Gray feathers.

Polymorphism Versus Inheritance

Inheritance simplifies code reusability, which allows you to create different instances of a parent class without rewriting code. Inheritance is a similar concept to polymorphism, so it’s easy to confuse the two. However, they’re not the same.

The difference is that polymorphism allows for customization. With polymorphism, you let child classes apply slight changes to the inherited methods and later identify which one to compile based on the input parameters. Check out our article on polymorphism in Java to learn more.

Using Java Inheritance in Your Code

Inheritance is a great tool to improve code reusability and model the real world, and Java gives you the right tools to seamlessly incorporate inheritance into your toolkit. The flexibility that its five types provide makes it extremely useful for representing real-world characteristics.

Moreover, you can use the super keyword and interfaces to implement multiple inheritance techniques. This enhances the abilities of inheritance to model real-world phenomena, making it very useful for developing video games and virtual reality programs.

java