The concept of inheritance is common in all of the object-oriented programming languages. In this blog, we will be discussing the syntax, terminology, and types of inheritance, particularly in Java. We will also explore its significance and understand why multiple inheritance is not supported in Java.
Table of Contents
Watch this video on Inheritance in Java to learn about it in detail:
What is Inheritance in Java?
Inheritance is a fundamental concept in object-oriented programming, where one class inherits the characteristics and behaviors of another class. This process is important as it aligns with the idea of hierarchical classification. It organizes information in a top-down manner. The main idea behind inheritance is that we can build new classes from existing classes.
To understand it in a better way, imagine you’re developing a manufacturing process for cars. It starts with a basic car design that includes important components such as the engine, wheels, chassis, and body, among other crucial parts. Now, your goal is to create different car models, including trucks, SUVs, and sedans. Rather than creating entirely different designs for every category, you choose to use the current basic car design and enhance it with features that are unique to each car model. This approach promotes the effective reusing of basic components, which optimizes the development process and encourages uniformity among these car models.
In Java programming, inheritance allows the transfer of attributes and methods from a parent object to its child object. This mechanism enables the new subclass to utilize all the methods and properties of its parent class while providing the flexibility to introduce additional features and methods specific to the subclass.
Are you interested in learning Java? Enroll in our Java online course now!
Syntax of Inheritance in Java
To inherit a class, you simply include the definition of one class in another by using the extends keyword. The syntax for inheriting a class in Java is as shown below:
class ChildClassname extends ParentClassname
{
//methods and fields
}
Terminologies Used in Inheritance
Some important terminologies that are used in the concept of inheritance are given below:
- Class: Class is a blueprint that’s used to make objects and to set the types of data and actions that those objects can have.
- Super Class/Parent Class/ Base Class: The class from which another class is derived is called a super class (also a base class or a parent class).
- Sub Class/Child Class/Derived Class/Extended Class: A class that is derived from the super class is called a subclass.
- Ambiguity: In Java, ambiguities represent issues that are not explicitly defined in the Java language specification. The ambiguity problem arises when a method or constructor is overloaded with multiple versions having the same name but different parameters.
- Interfaces: The interface in Java serves as a way to achieve abstraction. It allows the declaration of abstract methods without providing their implementation. This feature is specifically designed for achieving abstraction and multiple inheritance in Java.
Want to ace your next Java interview? Check out our recent blog post about the most common Java interview questions and answers!
Why is Inheritance Needed in Java?
Inheritance in Java serves several essential purposes that contribute to the effectiveness and flexibility of object-oriented programming. Here are some key reasons why inheritance is needed in Java:
- Code Reusability: Inheritance allows a class to inherit attributes and methods from another class. This promotes code reuse, as common functionalities can be defined in a base class and inherited by multiple subclasses. This helps avoid redundancy and leads to more maintainable code.
- Hierarchy and Organization: Inheritance facilitates the creation of a hierarchical structure of classes. This hierarchy reflects the relationships between different entities in a system. It enhances the organization of code, making it more intuitive and easier to understand.
- Polymorphism: Through inheritance, Java supports polymorphism, which allows objects of different classes to be treated as objects of a common base class. This flexibility enables the creation of more generalized and adaptable code.
- Overriding and Extending Functionality: Subclasses can override methods of the superclass, providing a specific implementation suited to their context. This enables customization and extension of functionality without modifying the original code in the superclass.
- Abstraction: Inheritance, coupled with abstract classes and interfaces, allows the creation of abstract types and methods. This abstraction helps in defining common characteristics and behaviors without specifying the details, promoting a clearer and more modular design.
- Enhanced Readability: Inheritance enhances the readability of code by emphasizing the relationships between classes. Developers can understand the structure and functionality of a class by examining its inheritance hierarchy.
Learn Java from scratch with this free Java Tutorial!
Get 100% Hike!
Master Most in Demand Skills Now!
Types of Inheritance in Java with Examples
There are five types of inheritance in Java, and each one of these types serves different purposes. These five types of inheritance include the following:
- Single inheritance
- Multilevel inheritance
- Hierarchical inheritance
- Multiple inheritance
- Hybrid inheritance
Single Inheritance
Single inheritance is the most simple form of inheritance in Java. In this type, a class derives properties from just one other class. In other words, there is only one derived class and one base class.
Let’s understand this with the help of an example:
import java.io.*;
import java.lang.*;
import java.util.*;
class Vehicle {
void start() {
System.out.println("Vehicle starting...");
}
void stop() {
System.out.println("Vehicle stopping...");
}
}
class Car extends Vehicle {
void drive() {
System.out.println("Car is driving...");
}
}
public class Main {
public static void main(String[] args) {
Car myCar = new Car();
// Accessing methods from the base class (Vehicle)
myCar.start(); // Vehicle starting...
myCar.stop(); // Vehicle stopping...
// Accessing method from the derived class (Car)
myCar.drive(); // Car is driving...
}
}
In this example, the Vehicle class has common methods start() and stop(), and the Car class inherits these methods. The Car class also has its own additional method, drive(). Objects of the Car class can call methods from both the Vehicle class and the Car class itself.
This code gives the following output:
Vehicle starting…
Vehicle stopping…
Car is driving…
Multilevel Inheritance
Multilevel inheritance occurs when a class inherits properties from another class, and this inherited class, in turn, passes on its properties to another class.
To understand this concept, let’s see an example:
import java.io.*;
import java.lang.*;
import java.util.*;
class MathOperation {
public int add(int a, int b) {
return a + b;
}
}
class AdvancedMathOperation extends MathOperation {
public int multiply(int a, int b) {
return a * b;
}
}
class ScientificCalculator extends AdvancedMathOperation {
public double squareRoot(double num) {
return Math.sqrt(num);
}
}
// Derived class
public class Main {
public static void main(String[] args) {
ScientificCalculator calculator = new ScientificCalculator();
int sum = calculator.add(5, 7); // Inherited from MathOperation
int product = calculator.multiply(3, 4); // Inherited from AdvancedMathOperation
double sqrtResult = calculator.squareRoot(25.0); // Specific to ScientificCalculator
System.out.println("Sum: " + sum);
System.out.println("Product: " + product);
System.out.println("Square Root: " + sqrtResult);
}
}
This Java program has a MathOperation class that can add numbers. The AdvancedMathOperation class extends this and performs multiplication. Further, the ScientificCalculator class extends AdvancedMathOperation and adds the capability to calculate square roots. Inside the main() function, an instance of the ScientificCalculator class, i.e., calculator, is created, through which we can access the methods of both parent classes.
This program will give the following output:
Sum: 12
Product: 12
Square Root: 5.0
Hierarchical Inheritance
In Java, hierarchical inheritance is a form of inheritance where multiple classes inherit from the same class. In other words, when several classes share and inherit features from a common class, it is referred to as hierarchical inheritance. Consider the following example to understand this concept better:
// Creating the base class
class BaseClass {
int firstNum = 10;
}
// Inheriting the base class in SubClass1
class SubClass1 extends BaseClass {
int secondNum = 1;
}
// Creating the subclass2 that inherits the base class
class SubClass2 extends BaseClass {
int thirdNum = 2;
}
// Creating the subclass3 that inherits the base class
class SubClass3 extends BaseClass {
int fourthNum = 3;
}
public class Main {
public static void main(String args[]) {
SubClass1 childObj1 = new SubClass1();
SubClass2 childObj2 = new SubClass2();
SubClass3 childObj3 = new SubClass3();
System.out.println("firstNum * secondNum = " + childObj1.firstNum * childObj1.secondNum);
System.out.println("firstNum * thirdNum = " + childObj2.firstNum * childObj2.thirdNum);
System.out.println("firstNum * fourthNum = " + childObj3.firstNum * childObj3.fourthNum);
}
}
This Java program involves a class BaseClass, and three subclasses SubClass1, SubClass2, and SubClass3. Each subclass inherits the firstNum variable from the base class and has its additional variable secondNum, thirdNum, and fourthNum, respectively.
In the Main class, objects of each subclass are created, and the program calculates and prints the product of firstNum from the base class and the additional variables introduced in each subclass.
This program gives the following output:
firstNum * secondNum = 10
firstNum * thirdNum = 20
firstNum * fourthNum = 30
Read about OOPs in Java to gain more knowledge.
Multiple Inheritance
In multiple inheritance, a class can inherit characteristics from more than one parent class. However, one problem arises when methods with identical signatures exist in both the parent classes and the subclass. When calling these types of methods, the compiler faces difficulty in determining which class’s method to invoke, leading to ambiguity in prioritizing the function calls. Multiple inheritance is not supported in Java directly, but we can achieve this with the help of interfaces.
Let’s see an example where multiple inheritance is achieved through interfaces:
// First interface
interface Engine {
void start();
}
// Second interface
interface Display {
void showInfo();
}
// Class implementing both interfaces, achieving multiple inheritance
class Car implements Engine, Display {
@Override
public void start() {
System.out.println("Car engine started");
}
@Override
public void showInfo() {
System.out.println("Car information displayed");
}
void drive() {
System.out.println("Car is on the move");
}
}
public class Main {
public static void main(String[] args) {
Car myCar = new Car();
myCar.start(); // Method from Engine interface
myCar.showInfo(); // Method from Display interface
myCar.drive(); // Method specific to the Car class
}
}
In this example, two interfaces, Engine and Display, define distinct sets of methods related to engine functionality and information display, respectively. The `Car` class implements both interfaces, inheriting and providing concrete implementations for the methods declared in each interface. This achieves a form of multiple inheritance as the `Car` class gains behavior from both the `Engine` and `Display` interfaces. The `Main` class showcases the usage of the `Car` class, invoking methods inherited from the interfaces and a specific method unique to the `Car` class. Multiple inheritance through interfaces allows for modular and flexible design, which eliminates the complications involved in traditional multiple inheritance through classes. It enables classes to inherit functionalities from multiple sources.
The output of this program is as shown below:
Car engine started
Car information displayed
Car is on the move
Learn about abstract classes in Java to gain in-depth knowledge.
Hybrid Inheritance
In hybrid inheritance, two or more types of inheritance are combined for better code organization and reusability. Although direct support for hybrid inheritance is not available in Java, it can be accomplished through the strategic combination of various inheritance types. These combinations include single and multiple inheritance, which can be achieved through interfaces; multilevel and hierarchical inheritance; hierarchical and single inheritance; and multiple and multilevel inheritance.
Let’s see an example of hybrid inheritance:
class ElectronicDevice
{
public void displayDevice()
{
System.out.println("Method defined inside ElectronicDevice class");
}
}
interface BluetoothEnabled
{
void connectBluetooth();
}
interface WiFiEnabled
{
void connectWiFi();
}
public class SmartPhone extends ElectronicDevice implements BluetoothEnabled, WiFiEnabled
{
public void connectBluetooth()
{
System.out.println("Bluetooth connected on the smartphone");
}
public void connectWiFi()
{
System.out.println("WiFi connected on the smartphone");
}
public void useApps()
{
System.out.println("Using applications on the smartphone");
}
public static void main(String args[])
{
SmartPhone myPhone = new SmartPhone();
System.out.println("Implementation of Hybrid Inheritance in Java");
myPhone.connectBluetooth();
myPhone.connectWiFi();
myPhone.displayDevice();
myPhone.useApps();
}
}
This example demonstrates the implementation of hybrid inheritance, where the SmartPhone class inherits from the ElectronicDevice class and implements the BluetoothEnabled and WiFiEnabled interfaces. The program then creates an instance of the SmartPhone class (myPhone) and invokes various methods, showcasing the inherited functionalities and the specific method defined in the SmartPhone class.
This program gives the following output:
Implementation of Hybrid Inheritance in Java
Bluetooth connected on the smartphone
WiFi connected on the smartphone
Method defined inside ElectronicDevice class
Using applications on the smartphone
Why is Multiple Inheritance Not Supported in Java?
Java does not support multiple inheritance, primarily to avoid the complexities and ambiguities that can arise when a class inherits from more than one class. Multiple inheritance can lead to the “diamond problem,” where a class inherits from two classes that have a common ancestor. This can result in ambiguity when there are conflicting methods or attributes in the common ancestor. Java, being designed with a focus on simplicity, robustness, and readability, opted for a single inheritance model to prevent such complications.
For example, consider two classes, A and B, both having a common ancestor, C. If a new class D attempts to inherit from both A and B and there’s a method or attribute in C that is overridden differently in A and B, it becomes unclear which implementation `D` should inherit. This ambiguity is known as the diamond problem and can make the code difficult to understand and maintain.
While Java does not support multiple inheritance through classes, it does provide a form of multiple inheritance through interfaces. Interfaces allow a class to implement multiple interfaces, each defining a contract of methods without the conflict issues associated with multiple inheritance in classes. This approach ensures clarity, avoids ambiguity, and promotes a more straightforward and maintainable codebase.
Conclusion
In Java, inheritance is a feature that plays a crucial role in enhancing code reusability, promoting a hierarchical class structure, and facilitating polymorphism. By allowing new classes to inherit properties and behaviors from existing ones, developers can reuse code efficiently, simplifying the software development process. The establishment of class hierarchies through inheritance contributes to a well-structured and modular design, making code more readable, maintainable, and adaptable to changes. Furthermore, inheritance supports method overriding, enables customization in subclasses, and encourages consistency and standardization by centralizing common attributes in superclasses. This feature simplifies maintenance tasks, reduces the likelihood of errors, and is integral to the object-oriented principles that underpin Java programming. Overall, inheritance in Java is indispensable for building scalable, flexible, and maintainable software solutions.