Inheritance in Java: A Detailed Explanation

Inheritance is one of the four fundamental principles of object-oriented programming (OOP) in Java, along with encapsulation, polymorphism, and abstraction. It allows a class to inherit properties and behaviors (fields and methods) from another class.

Basic Concepts

1. Superclass and Subclass

  • Superclass (Parent class): The class whose features are inherited
  • Subclass (Child class): The class that inherits the features

2. The extends Keyword

Java uses the extends keyword to establish inheritance:

class Subclass extends Superclass {
    // subclass members
}

Types of Inheritance

1. Single Inheritance

A subclass inherits from one superclass.

class Animal {
    void eat() {
        System.out.println("Eating...");
    }
}

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

2. Multilevel Inheritance

A chain of inheritance.

class Animal {
    void eat() { System.out.println("Eating..."); }
}

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

class Puppy extends Dog {
    void weep() { System.out.println("Weeping..."); }
}

3. Hierarchical Inheritance

Multiple subclasses inherit from one superclass.

class Animal {
    void eat() { System.out.println("Eating..."); }
}

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

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

Important Features

1. Method Overriding

Subclasses can provide specific implementation of a method already defined in superclass.

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

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

2. The super Keyword

Used to:

  • Call superclass methods
  • Access superclass fields
  • Call superclass constructor
class Animal {
    String color = "white";
}

class Dog extends Animal {
    String color = "black";

    void printColor() {
        System.out.println(color);        // black
        System.out.println(super.color);  // white
    }
}

3. Constructor Chaining

When creating a subclass object, the superclass constructor is called first.

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

class Dog extends Animal {
    Dog() {
        super(); // implicit if not written
        System.out.println("Dog constructor");
    }
}

Inheritance and Access Modifiers

  • public: Accessible everywhere
  • protected: Accessible within package and subclasses
  • default (no modifier): Accessible within package only
  • private: Not accessible in subclass

The final Keyword and Inheritance

  • final class: Cannot be extended
  • final method: Cannot be overridden
  • final variable: Cannot be reassigned
final class FinalClass { /* cannot be extended */ }

class Parent {
    final void finalMethod() { /* cannot be overridden */ }
}

Abstract Classes and Inheritance

Abstract classes are designed to be inherited and cannot be instantiated.

abstract class Animal {
    abstract void makeSound();

    void eat() {
        System.out.println("Eating...");
    }
}

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

Interfaces and Inheritance

A class can implement multiple interfaces, achieving multiple inheritance of type.

interface Walkable {
    void walk();
}

interface Swimmable {
    void swim();
}

class Duck implements Walkable, Swimmable {
    public void walk() { System.out.println("Duck walking"); }
    public void swim() { System.out.println("Duck swimming"); }
}

Object Class: The Ultimate Superclass

All classes in Java implicitly extend the Object class if no other superclass is specified.

class MyClass { 
    // implicitly extends Object
}

Benefits of Inheritance

  1. Code Reusability: Avoid duplicating code
  2. Method Overriding: Runtime polymorphism
  3. Abstraction: Hide implementation details
  4. Extensibility: Easy to add new features

Limitations of Inheritance

  1. Tight coupling between classes
  2. Multiple inheritance not supported for classes (only through interfaces)
  3. Can make code more complex if overused

Best Practices

  1. Favor composition over inheritance when possible
  2. Use inheritance for "is-a" relationships
  3. Keep inheritance hierarchies shallow
  4. Avoid inheriting from concrete classes when possible

Inheritance is a powerful tool in Java that, when used appropriately, can lead to clean, maintainable, and efficient code structures.