Inheritance is a key feature of object-oriented programming (OOP) that allows one class to inherit properties and behaviours from another class. In Java, inheritance enables code reuse and establishes a relationship between classes, making the code modular, extensible, and easier to manage.

What is Inheritance?

In Java, inheritance allows a new class (called the subclass or child class) to inherit fields and methods from an existing class (called the superclass or parent class). The subclass can then use or override these inherited methods and fields, allowing it to share and extend the functionality of the superclass.

Syntax

Inheritance is implemented in Java using the extends keyword. Here’s the basic syntax:

class ParentClass {
    // Fields and methods
}

class ChildClass extends ParentClass {
    // Fields and methods specific to ChildClass
}

In this example, ChildClass inherits from ParentClass, making ParentClass the superclass and ChildClass the subclass.

Example: Basic Inheritance

Here’s a simple example to demonstrate inheritance in Java. We’ll create a Vehicle superclass and a Car subclass that inherits from Vehicle.

// Superclass
class Vehicle {
    int speed;
    String color;

    void displayInfo() {
        System.out.println("Speed: " + speed + " km/h");
        System.out.println("Color: " + color);
    }
}

// Subclass
class Car extends Vehicle {
    int doors;

    void showDetails() {
        displayInfo();
        System.out.println("Doors: " + doors);
    }
}

public class Main {
    public static void main(String[] args) {
        Car myCar = new Car();
        myCar.speed = 150;
        myCar.color = "Red";
        myCar.doors = 4;
        myCar.showDetails();
    }
}

Output:

Speed: 150 km/h
Color: Red
Doors: 4

In this example:

  • The Vehicle class is the superclass, containing speed and color fields, along with the displayInfo() method.
  • The Car class is the subclass, inheriting the properties and behavior from Vehicle. It also introduces its own doors field and showDetails() method.

Types of Inheritance in Java

Java supports single inheritance and hierarchical inheritance but does not support multiple inheritance directly. Here’s a quick look at the types of inheritance Java supports:

  1. Single Inheritance: A class inherits from only one superclass. class Parent { } class Child extends Parent { }
  2. Multilevel Inheritance: A class inherits from a subclass, forming a chain. class GrandParent { } class Parent extends GrandParent { } class Child extends Parent { }
  3. Hierarchical Inheritance: Multiple classes inherit from a single superclass. class Parent { } class Child1 extends Parent { } class Child2 extends Parent { }

Java does not support multiple inheritance (where a class inherits from more than one superclass) to avoid complexity and ambiguity issues, such as the diamond problem.

Overriding Methods in Inheritance

When a subclass defines a method with the same signature as a method in its superclass, it overrides that method. This allows the subclass to provide its own specific implementation while still maintaining the superclass’s contract.

Example of Method Overriding

class Animal {
    void sound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    void sound() {
        System.out.println("Dog barks");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myAnimal = new Dog();
        myAnimal.sound();  // Output: Dog barks
    }
}

Here:

  • The Dog class overrides the sound() method of the Animal class.
  • The @Override annotation ensures that the method is overriding a superclass method, making the code easier to understand and preventing errors.

Access Modifiers in Inheritance

In Java, access modifiers control the visibility of fields and methods across classes:

  • public: Accessible in any class.
  • protected: Accessible within the same package and by subclasses.
  • default (no modifier): Accessible within the same package.
  • private: Accessible only within the declaring class (not inherited by subclasses).

For example:

class Animal {
    protected String type = "Mammal";  // Protected field
}

class Dog extends Animal {
    void displayType() {
        System.out.println("Type: " + type);  // Accessing protected field
    }
}

The super Keyword

The super keyword is used to refer to the superclass’s methods and fields. It’s particularly useful when you want to call a superclass method that has been overridden in the subclass.

Example of super Keyword

class Animal {
    void sound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    void sound() {
        super.sound();  // Calls the superclass's sound() method
        System.out.println("Dog barks");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog();
        myDog.sound();
    }
}

Output:

Animal makes a sound
Dog barks

In this example, super.sound() calls the sound() method in the Animal superclass before executing the subclass’s sound() method.

Constructor Chaining in Inheritance

When a subclass is created, it automatically calls the superclass’s constructor first. This is known as constructor chaining. You can explicitly call a superclass constructor with super().

class Animal {
    Animal() {
        System.out.println("Animal constructor called");
    }
}

class Dog extends Animal {
    Dog() {
        super();  // Calls Animal's constructor
        System.out.println("Dog constructor called");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog();
    }
}

Output:

Animal constructor called
Dog constructor called

Benefits of Inheritance

  • Code Reusability: Allows reusing the code of existing classes without rewriting it.
  • Code Maintenance: Changes in the superclass are reflected automatically in the subclasses.
  • Extensibility: Adds new features or overrides existing ones in the subclass without modifying the superclass.
  • Polymorphism: Allows subclasses to be treated as instances of their superclass, enabling dynamic method binding.

Summary

Inheritance in Java is a fundamental OOP concept that facilitates code reuse and logical organization. It allows classes to build on each other’s functionality, improving maintainability and enabling polymorphic behaviour. Using inheritance effectively can make Java programs more modular, readable, and efficient.