Java Inheritance


Inheritance is one of the core concepts of Object-Oriented Programming (OOP) in Java. It allows a class to acquire properties and behaviors (fields and methods) from another class, promoting code reuse and establishing a hierarchical relationship between classes. With inheritance, you can create a more flexible and maintainable codebase by extending existing classes instead of rewriting code.

In this guide, we will explore Java inheritance, its syntax, types, key features, and provide practical examples to help you understand how inheritance works in Java.

Table of Contents

  1. What is Java Inheritance?
  2. Syntax of Java Inheritance
  3. Types of Inheritance in Java
  4. How Inheritance Works in Java
  5. Overriding Methods in Inheritance
  6. Super Keyword in Java
  7. Constructor Inheritance
  8. Advantages and Disadvantages of Inheritance

What is Java Inheritance?

Inheritance in Java allows a class (called the subclass or child class) to inherit fields and methods from another class (called the superclass or parent class). This mechanism provides a way to create a new class by reusing the code from an existing class. Inheritance represents an is-a relationship, where the child class is a type of the parent class.

For example, consider a class Animal and a class Dog. A Dog is an Animal, so the Dog class can inherit the properties and behaviors of the Animal class.


Syntax of Java Inheritance

To achieve inheritance in Java, the subclass uses the extends keyword to inherit from the superclass.

class Superclass {
    // Fields and methods of the superclass
}

class Subclass extends Superclass {
    // Fields and methods of the subclass
}

Example:

class Animal {
    void eat() {
        System.out.println("This animal eats food.");
    }
}

class Dog extends Animal {
    void bark() {
        System.out.println("The dog barks.");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.eat();  // Inherited from Animal class
        dog.bark(); // Specific to Dog class
    }
}

Output:

This animal eats food.
The dog barks.

In this example, the Dog class inherits the eat() method from the Animal class.


Types of Inheritance in Java

Single Inheritance

Single inheritance occurs when a subclass inherits from only one superclass. This is the simplest form of inheritance.

class Animal {
    void eat() {
        System.out.println("This animal eats food.");
    }
}

class Dog extends Animal {
    void bark() {
        System.out.println("The dog barks.");
    }
}

Multilevel Inheritance

Multilevel inheritance occurs when a class is derived from another class, which is also derived from another class. It forms a chain of inheritance.

class Animal {
    void eat() {
        System.out.println("This animal eats food.");
    }
}

class Dog extends Animal {
    void bark() {
        System.out.println("The dog barks.");
    }
}

class Puppy extends Dog {
    void play() {
        System.out.println("The puppy plays.");
    }
}

Hierarchical Inheritance

Hierarchical inheritance occurs when multiple subclasses inherit from a single superclass. All subclasses can access the properties and methods of the superclass.

class Animal {
    void eat() {
        System.out.println("This animal eats food.");
    }
}

class Dog extends Animal {
    void bark() {
        System.out.println("The dog barks.");
    }
}

class Cat extends Animal {
    void meow() {
        System.out.println("The cat meows.");
    }
}

Multiple Inheritance (via Interfaces)

Java does not support multiple inheritance with classes, meaning a class cannot inherit from multiple classes directly. However, multiple inheritance can be achieved using interfaces. A class can implement multiple interfaces, thereby inheriting behavior from multiple sources.

interface Animal {
    void eat();
}

interface Pet {
    void play();
}

class Dog implements Animal, Pet {
    public void eat() {
        System.out.println("The dog eats.");
    }

    public void play() {
        System.out.println("The dog plays.");
    }
}

How Inheritance Works in Java

When a subclass inherits from a superclass, it automatically inherits the non-private members (fields and methods) of the superclass. The subclass can also override methods from the superclass and add its own specific behaviors. However, the subclass does not inherit constructors from the superclass.

The subclass can access the inherited members directly or modify them as needed.


Overriding Methods in Inheritance

One of the key features of inheritance is method overriding, where a subclass provides its own implementation of a method that is already defined in its superclass.

To override a method, the subclass defines a method with the same signature (name, return type, and parameters) as the method in the superclass.

Example:

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

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

class Main {
    public static void main(String[] args) {
        Animal animal = new Animal();
        animal.sound(); // Output: Animal makes a sound

        Dog dog = new Dog();
        dog.sound(); // Output: Dog barks
    }
}

Output:

Animal makes a sound
Dog barks

In this example, the Dog class overrides the sound() method of the Animal class to provide a specific implementation.


Super Keyword in Java

The super keyword is used to refer to the superclass in the subclass. It can be used to:

  • Call superclass methods.
  • Access superclass fields.
  • Invoke the superclass constructor.

Example:

class Animal {
    void eat() {
        System.out.println("This animal eats food.");
    }
}

class Dog extends Animal {
    void eat() {
        super.eat();  // Calling the superclass method
        System.out.println("The dog eats bones.");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.eat(); // Calls Dog's eat() and Animal's eat()
    }
}

Output:

This animal eats food.
The dog eats bones.

In this example, super.eat() invokes the eat() method from the superclass Animal.


Constructor Inheritance

Constructors are not inherited by subclasses in Java. However, a subclass can invoke the constructor of its superclass using the super() keyword.

Example:

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

class Dog extends Animal {
    Dog() {
        super();  // Calling the superclass constructor
        System.out.println("Dog Constructor");
    }
}

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

Output:

Animal Constructor
Dog Constructor

Here, the Dog class calls the constructor of the Animal class using super(), ensuring proper initialization of the superclass before the subclass constructor is executed.


Advantages and Disadvantages of Inheritance

Advantages:

  1. Code Reusability: Inheritance allows a subclass to reuse the methods and fields of the superclass, avoiding redundancy.
  2. Method Overriding: Subclasses can customize or extend the behavior of methods inherited from the superclass.
  3. Hierarchical Classification: Inheritance enables the creation of hierarchical class structures, promoting organization and clarity.

Disadvantages:

  1. Tight Coupling: Inheritance can lead to tight coupling between classes, making changes in the parent class affect the child class.
  2. Complexity: Overuse of inheritance can create complex and difficult-to-maintain class hierarchies.
  3. Inflexibility: Inheritance may not always be the best approach, especially if the relationship between classes doesn't fit an "is-a" model.