Are you stuck in achieving code reusability, overriding a method, or gaining abstraction in your Java program? Then don’t worry! A Java OOP concept named “inheritance” is available to rescue you. This concept specifically helps in achieving a high level of code reusability along with the abstraction in Java. The “inheritance” follows the “IS-A” type of relationship between the classes to use properties of one class into another.

In this guide, we will explore every aspect of Inheritance in Java by covering below sections:

  • What is Inheritance in Java?
  • How to Implement Single Inheritance in Java?
  • How to Implement Multi-Level Inheritance in Java?
  • How to Implement Hierarchical Inheritance in Java?
  • How to Implement Hybrid Inheritance in Java?
  • How to Implement Multiple Inheritance Alternatively in Java?
  • Why Multiple Inheritance is Not Allowed in Java? | What is the Diamond Problem?

What is Inheritance in Java?

The “Inheritance” is a main pillar of the Java OOP concept. It allows users to utilize the class properties(methods or variables) in another class. This prevents the creation of the same method into another class and also hides the working details of a method from the inherited class. This helps in achieving the reusability and abstraction concepts.

General Syntax for Inheritance

public class DerivedClasss extends BaseClass{

}

Its implementation format in a Java code is:

class? BaseClass{
// BaseClass data variables or member functions
}
public class DerivedClasss extends BaseClass{
// DerivedClasss data variables or member functions
}

In the above syntax:

  • The “extends” keyword indicates that the class “DerivedClasss” is inherited from another class namely “BaseClass”.
  • Class: It stores a collection of data variables or member functions to perform specific operations.
  • BaseClass: The super, parent, or base class is the main class whose data variables or member functions are going to be inherited.
  • DerivedClass: The sub, child, or derived class is the one which inherits the data variables or member function of the “BaseClass”. It can overload the member function of “BaseClass” to add extra lines of code.

What is the “IS-A” Relationship in Java?

The “IS-A” relationship is a fundamental principle in OOP that solely represents inheritance. It says that the derived class is the specialized or inherited version of the base/super class. This relationship is built using the “extends” keyword between two classes. The “IS-A” relationship is not specific to single inheritance as it can be applied to both single and multiple inheritance scenarios. The real-time examples will be:

  • Laptop is a device > Laptop class is inherited from a “device” class.
  • Tablet is a device > Tablet class is inherited from a “device” class.
  • Smartphone is a Tablet > Smartphone is a derived class of base “tablet” class.
  • Smartwatch is a Smartphone > Smartwatch is a sub/derived class of the super/base “Smartphone” class.

Important Points to Remember:

  • The “Cyclic Inheritance” is not allowed in Java, as the base class cannot inherit the properties of a derived class.
  • The “Multiple Inheritance” is not supported by Java. However, using the “interfaces” users can use multiple inheritance.
  • The “constructors” can not be inherited yet the user can inherit the class members and class variables.
  • The data variables declared in a “private” scope are unavailable in the derived inherited class.
  • The instance of a super/base class can be assigned to a sub/derived class and vice versa. These techniques are known as “downcasting” and “upcasting”.
  • The “final” type class is not accessible via inheritance.

Access Modifiers

The “Access Modifiers” specify the availability of class variables or member functions residing inside the “Super/base” class. This availability is set using the four access modifiers, which are described below:

  • Default: The “default” access modifier is set automatically when no modifiers are provided by the user. This class scope resides inside the single package in which it is defined and is non-accessible from any other package.
  • Public: The “public” access modifier has full access and it can be accessed to every part of your code even from different Java packages. 
  • Protected: The classes with a “protected” access modifier are accessed only by their inherited child class.
  • Private: A class having the access modifier of “Private” is not available for inherited classes.

Types of Inheritance

Inheritance can be implemented using five different approaches which are listed below:

  • Single Inheritance.
  • Multi-Level Inheritance.
  • Hierarchical Inheritance.
  • Hybrid Inheritance.
  • Multiple Inheritance.

How to Implement Single Inheritance in Java?

In “single inheritance”, the subclass inherits the class properties of a single base/super class. To access the properties of a base/super class, the object of derived/subclass is used. The visual representation of single inheritance is shown below:

The Java program to implement the single inheritance is mentioned below:

class Laptop{
void company(){
  System.out.println("The company name is: Toshiba");
}
}
class processing extends Laptop{
void core(){
  System.out.println("core i7");
}
}
class mainClass{
public static void main(String args[]){
  processing subClassObj = new processing();
  subClassObj.company();
  subClassObj.core();
}
}

In the above code snippet:

  • First, create a class named “Laptop” which acts as our super or base class. This class contains a member function named “company()” that displays a random message on the console.
  • Next, define a derived class named “processing” which inherits or extends the base class “Laptop” using the “extends” keyword.
  • This class also contains a member function named “core()” to display a dummy message on the console.
  • After that, create a class “mainClass” which contains a “main()” method. Create an object of derived class “processing” inside it called “subClassObj”.
  • Finally, use this object to invoke the member functions residing in both base and derived classes. 

Output confirms the creation of single inheritance:

How to Implement Multi-Level Inheritance in Java?

In “Multi-Level” inheritance, there is a top-to-bottom inherited hierarchy. Every derived/subclass has at most one base class and this base class must contain another superclass as well. 

Consider a scenario in which the child has one father and then that father has also a father, which is the grandfather of the child. The “child” or subclass can not directly access the “grandfather” superclass as it must go through the “father” or intermediary class.

The visual representation is shown as:

The implementation of multilevel inheritance in Java code is shown below:

class Brand {
  void company() {
  System.out.println("\n'Random Electronics' => SuperClass");
  }
}
class Display extends Brand {
static void screenSize() {
  System.out.println("\n'20.5 inches' => intermediary Base Class 1");
}
void displayInfo() {
  System.out.println("\n'LED-backlit'=> intermediary Base Class 1");
}
}
class Processing extends Display {
void core() {
  System.out.println("\n'Intel Core i9' => intermediary Base Class 2");
}
}
class subclass extends Processing {
public static void main(String[] args) {
  System.out.println("\n Derived Subclass");
  subclass curr = new subclass();
  curr.core();
  curr.displayInfo();
  Display.screenSize();
  curr.company();
}
}

The above code works like this:

  • First, create a class “Brand” which contains a “company()” named method to display random text. This class acts as a super base class.
  • Next, define a derived or subclass named “Display” which is inherited by the super “Brand” class using the “extends” keyword. This class contains two methods namely “screenSize()” having the type of “static” and the “displayInfo()” to display dummy data.
  • Then, declare another derived class that inherits the properties of the “Display” class. It also contains a method named “core()” that displays random text.
  • After that, define another derived or subclass class named “subclass” which extends the already created “processing” class. This class contains a “main()” method in which the object of “subclass” is created, namely “curr”. 
  • This created object is then used to invoke the methods residing in all base classes. But the “screenSize()” static method is invoked using the “Display” class.

The output generated for the above code is as follows:

How to Implement Hierarchical Inheritance in Java?

The “Hierarchical” inheritance offers a single base/super class whose properties are inherited by multiple derived classes directly without the involvement of an intermediary class. For instance, three derived classes are being inherited by a single “Base/Super Class”, as shown visually:

Now, let’s implement the discussed scenario in Java:

class Brand {
void company() {
  System.out.println("'Random' => Super/Base Class");
}
}
class Display extends Brand {
void displayInfo() {
  System.out.println("Display information: High resolution => Derived Class Method\n");
}
}
class Laptop extends Brand {
void processingInfo() {
  System.out.println("Processing information: Multi-core support => Derived Class Method\n");
}
}
class Smartphone extends Brand {
void core() {
  System.out.println("'ARM Processor': Smartphone Class => Derived Class Method\n");
}
}
public class starter{
public static void main(String[] args) {
  Display DisplayObj = new Display();
  Laptop laptopObj = new Laptop();
  Smartphone smartphoneObj = new Smartphone();
  System.out.println("Accessing Single Super Class Methods From All Derived Classes:\n\n");

  DisplayObj.company();
  DisplayObj.displayInfo();

  laptopObj.company();
  laptopObj.processingInfo();

  smartphoneObj.company();
  smartphoneObj.core();
}
}

In the above code snippet:

  • Initially, declare a class “Brand” which contains a single method of “company()”. This class acts as a superclass. 
  • Next, create three derived/subclasses namely “Display”, “Laptop”, and “Smartphone” which inherit the single super class “Brand” properties.
  • Each class contains unique methods namely “displayInfo()”, “processingInfo()”, and “core()”. These methods print different dummy messages on the console.
  • After that, create an object for all mentioned derived/subclasses namely “DisplayObj”, “laptopObj”, and “smartphoneObj”. 
  • In the end, use the objects to invoke their methods and the super/base class methods to confirm the implementation of “Hierarchical Inheritance”.

The output shows that each derived class object has called the Super/base class methods:

How to Implement Hybrid Inheritance in Java?

Hybrid inheritance can be the combination of “Single”, “Multi-Level”, or “Hierarchical” inheritance. The “multiple” inheritance which is not allowed by Java, can be implemented in Hybrid Inheritance. With the combined form of “multi-level” and “hierarchical” inheritances, without the usage of interfaces. 

The basic graphical representation of hybrid inheritance is shown below. In this graph, the combined form of hierarchical and multi-level inheritance is shown:

Let’s implement the illustrated graph in Java for a broader explanation:

class Device {
public void displayInfo(String superParam) {
System.out.println(superParam + "==> This method is from a Super/Base class for all Classes.\n");
}
}
class Laptop extends Device {
public void displayInfo(String superParam) {
  System.out.println(superParam + "==> This method is a Derived Class via Hierarchy Inheritance.\n");
}
}
class Tablet extends Device {
public void displayInfo(String superParam) {
  System.out.println(superParam + "==> This method is a Derived Class via hierarchy Inheritance\n");
}
}

class Smartphone extends Laptop {
public void displayInfo(String superParam, String dummy) {
  System.out.println(superParam +", " + dummy + "\n ==> inherits from Super class and has multi-level inheritance with Laptop class\n");
}
}
class Smartwatch extends Smartphone {
  public void displayInfo(String superParam, String dummy, String version) {
  System.out.println(superParam + ", " + dummy + ", " + version + "\n ==> inherits from Smartphone and has multi-level inheritance with Smartphone class\n");
  }
}
class starter{
public static void main(String args[]) {
  Laptop laptopObj = new Laptop();
  Tablet tabletObj = new Tablet();
  Device deviceObj = new Device();
  Smartphone phoneObj = new Smartphone();
  Smartwatch watchObj = new Smartwatch();

  genericDevice.displayInfo("Device");
  myLaptop.displayInfo("Laptop");
  myTablet.displayInfo("Tablet");
  myPhone.displayInfo("Smartphone", "random");
  myWatch.displayInfo("Smartwatch", "randomWatch", "Modular");
}
}

The working of the mentioned code is described below:

  • First, create a class “Device” that has a method “displayInfo()” and accepts String type parameter “superParam”.
  • Next, the class “Laptop” is created which inherits the superclass “Device” properties. It contains the same method “displayInfo” with a single parameter.
  • In addition, create another class “Tablet” which extends from the same “Device” class. This shows the implementation of “Hierarchy” inheritance as two classes are inherited from the same superclass.
  • Now, build a “Smartphone” class that extends the properties of a “Laptop” class. This class also contains the “displayInfo()” method but with an extra argument of “dummy”. The values of both arguments are then displayed on the console as well.
  • Moreover, create a “smartwatch” class which is extended from a “Smartphone” class. This implements the “multi-level” inheritance because the “Smartphone” derived class is the parent of another “Smartwatch” derived class.
  • After that, define a “main()” method inside the “starter” class. Inside it, create objects named “laptopObj”, “tabletObj”, “deviceObj”, “phoneObj”, and “watchObj” for all classes.
  • In the end, use these objects to invoke the “displayInfo()” method residing inside each class. Also, pass the required parameters to the invoked method accordingly.

Output for the mentioned code appears like this:

How to Implement Multiple Inheritance Alternatively in Java?

In “Multiple Inheritance”, more than one base/superclass inherits the single derived/subclass. This inherited subclass interacts and uses the data members or data variables provided by all superclasses. 

Unfortunately, Java does not allow users to implement “Multiple” inheritance. However, the same functionality can be achieved by the utilization of “interfaces” instead of multiple classes. These interfaces act as a class and Java allows them to be linked with the derived class. The interface methods can be static or abstract:

  • In a static interface method, the data member function is declared and defined inside the “interface” scope. 
  • In an abstract interface method, the data member functions are declared inside the “interface” scope and defined inside the “derived” or subclass body.

Its graphical representation is shown as:

Let’s create a basic Java program to implement the discussed multiple inheritances alternatively:

interface brand{
  public void company();
}
interface display {
  public static void screenSize() {
  System.out.println("\n'15.7' => Static Base Interface");
  };
}
class processing {
  void core(){
  System.out.println("\n'core i7' => Base Class");
  }
}
class derivedClass extends processing implements brand, display{
  public void company() {
  System.out.println("\n'Toshiba' => Abstract Base Interface");
  }
  public static void main(String[] args) {
  derivedClass curr = new derivedClass();
  curr.core();
  curr.company();
  display.screenSize();
  }
}

The above code works like this:

  • First, create an interface named “brand” which declares a public type method “company()”. This makes the “company” method work like an abstract method.
  • Next, create another interface “display” having the static method of “screenSize()”. This method displays a dummy text on the console.
  • Then, define a class named “processing” which contains a function of “core()” to print a random text.
  • After that, create a derived/subclass class named “derivedClass”. It uses the “extends” keyword to inherit the properties of the “processing” class.
  • In addition, the “implements” keyword is used to inherit the defined “brand” and “display” interfaces.
  • Inside this class, define the abstract “company()” function which displays a random text on the console window.
  • In the end, define a “main()” method and inside it create an object namely “curr” for “derivedClass”. This object is then used to invoke the base class and interface methods.

Output for the mentioned code shows that the establishment of “Multiple” inheritance:

Why Multiple Inheritance is Not Allowed in Java? | What is the Diamond Problem?

The unsupportivity of “multiple” inheritance is due to the “Diamond” problem. The “Diamond” problem is raised when the derived class calls a method that is defined in both parent classes. So there is ambiguity and the compiler does not know which class methods should be invoked. This raised the “Unresolved compilation problem” error or “Diamond” problem.

For a better understanding have a look at the below graphical demonstration of the “Diamond Problem”:

Take a look at the occurrence of a diamond problem in a Java program:

interface superClass {
default void show() {
  System.out.println("Super Class");
}
}
interface leftparent extends superClass{
default void show() {
  System.out.println("Left parent");
}
}
interface rightParent extends superClass{
default void show() {
  System.out.println("Right Parent");
}
}
class starter implements leftparent, rightParent {
public static void main(String[] args) {
  starter obj = new starter();
  obj.show();
}
}

In the above code:

  • Single super/base interface named “superClass” is created.
  • The properties of this interface are then inherited by two derived interfaces namely “leftParent” and “rightParent”.
  • Both of these interfaces hold the same method named “show()” and display different data on the console.
  • After that, create a class “starter” which inherits both derived classes using the “implements” keyword. The object of this class is then created to invoke the “show()” method.

Output for the above code is shown below:

Solution of Diamond Problem

To resolve the “Diamond” problem, apply the “@Override” annotation to specifically tell the compiler about the class whose method needs to be executed. The “super” keyword is also used to select the superclass methods. For instance, the “show()” method is overridden to execute the “show()” method of a “leftParent” class:

interface superClass {
default void show() {
  System.out.println("Super Class");
}
}
interface leftParent extends superClass{
default void show() {
  System.out.println("Left parent Class Method is Executed");
}
}
interface rightParent extends superClass{
default void show() {
  System.out.println("Right parent Class Method is Executed");
}
}
class csvReading implements leftParent, rightParent {
@Override
public void show() {
  leftParent.super.show();
}
public static void main(String[] args) {
  csvReading diamondObj = new csvReading();
  diamondObj.show();
}
}

The output confirms that the diamond problem has been resolved:

That’s all about inheritance in Java.

Conclusion

The “inheritance” is a core concept of OOP, it allows users to inherit the properties of first-class into the second class to increase the reusability of code. The inheritance is performed by the usage of an “extends” keyword. There are five types of inheritance namely “Single”, “Multiple”, “Multi-Level”, “Hierarchical”, and “Hybrid”. Multiple inheritance is performed using “interfaces” instead of classes which are inherited using the “implements” keyword. This guide has explained the inheritance concept of Java.