Java Inheritance

In Java, inheritance is a fundamental pillar of Object-Oriented Programming (OOP). It is a mechanism that allows one class (the subclass or child) to acquire the fields and methods of another class (the superclass or parent). Think of it as a way to create a specialized version of an existing class without rewriting all the code from scratch.

Inheritance represents the IS-A relationship. For example, a "Manager" is-a "Employee," or a "Car" is-a "Vehicle."

Developer Tip: Inheritance is primarily used to achieve runtime polymorphism and code reusability. If you find yourself copying and pasting methods between classes, it’s a sign that you might need a common superclass.

Definition:

  • Inheritance allows a subclass to inherit the non-private attributes and methods of its superclass. This establishes a hierarchy where common logic lives in the parent, and specific logic lives in the children.
Watch Out: While a subclass inherits almost everything, it cannot inherit private members of the superclass directly. You must use public or protected getter/setter methods to access them.

Syntax:

  • To create a subclass, use the extends keyword. This tells the Java compiler that your new class is building upon the foundation of an existing one.
  • Example:
class Employee {
    float salary = 50000;
}

class Manager extends Employee {
    int bonus = 10000;
    
    void displayTotal() {
        // Accessing 'salary' inherited from Employee
        System.out.println("Total Compensation: " + (salary + bonus));
    }
}
Best Practice: Always use the @Override annotation when you redefine a parent method in a subclass. This helps the compiler catch errors if you accidentally misspell the method name or change the parameters.

There are different types of inheritance supported by Java classes:

Single Inheritance:

  • This is the simplest form, where one subclass inherits from exactly one superclass. It creates a direct parent-child relationship.
  • Example (A basic User system):
class User {
    String username;
    void login() { System.out.println("User logged in"); }
}

class Admin extends User {
    void deleteUser() { System.out.println("User deleted"); }
}

Multilevel Inheritance:

  • In this scenario, a class acts as a subclass to one class and a superclass to another. This creates a "chain" of inheritance.
  • Example (A real-world hardware hierarchy):
class Device {
    void powerOn() { System.out.println("Device is on"); }
}

class Smartphone extends Device {
    void connectToWifi() { System.out.println("Connecting..."); }
}

class iPhone extends Smartphone {
    void useFaceID() { System.out.println("Scanning face..."); }
}
Common Mistake: Beginners often create deeply nested multilevel hierarchies (e.g., 5+ levels). This makes the code fragile and very hard to debug. Try to keep your inheritance "tree" shallow.

Hierarchical Inheritance:

  • In hierarchical inheritance, multiple subclasses share the same parent class. This is common when you have several variations of a base concept.
  • Example:
class Account {
    void deposit() { /* common logic */ }
}

class SavingsAccount extends Account {
    void addInterest() { /* specific logic */ }
}

class CheckingAccount extends Account {
    void writeCheck() { /* specific logic */ }
}

Multiple Inheritance (Not Supported in Java Classes):

  • Multiple inheritance occurs when a subclass tries to inherit from more than one superclass (e.g., class C extends A, B).
  • Why is it blocked? Java does not support this for classes to avoid the "Diamond Problem," where a conflict arises if two parent classes have methods with the same name.
  • However, Java allows a class to implement multiple interfaces, which provides a safe way to achieve similar results.
Watch Out: If you try to extend more than one class, your code will fail to compile with an "Identifier expected" or "Unexpected token" error.

Summary

Inheritance is a powerful tool for organizing your Java applications. It promotes the "Don't Repeat Yourself" (DRY) principle by moving shared logic to a central superclass. By mastering single, multilevel, and hierarchical inheritance, you can build modular systems that are easier to maintain and extend over time.

Best Practice: Favor "Composition over Inheritance" when a relationship is not strictly "IS-A." If a class only needs a few features from another class, it is often better to create an instance of that class as a field rather than inheriting from it.