Introduction
Inheritance is one of the four fundamental principles of object-oriented programming (OOP) in Java, alongside encapsulation, polymorphism, and abstraction. It enables a class (called a subclass or child class) to inherit fields and methods from another class (called a superclass or parent class). This mechanism promotes code reuse, establishes hierarchical relationships between classes, and supports the creation of more specialized types from general ones. Understanding basic inheritance—including how to define parent and child classes, use the extends keyword, and manage constructors—is essential for building modular, maintainable, and extensible Java applications.
1. What Is Inheritance?
Inheritance allows a new class to acquire the properties (fields) and behaviors (methods) of an existing class. The existing class is the superclass, and the new class is the subclass.
Key Benefits
- Code Reusability: Avoid rewriting common code.
- Method Overriding: Customize or extend inherited behavior.
- Hierarchical Organization: Model real-world "is-a" relationships (e.g., a
Dogis aAnimal).
2. Syntax: The extends Keyword
A subclass is declared using the extends keyword followed by the superclass name.
class Superclass {
// Fields and methods
}
class Subclass extends Superclass {
// Additional or overridden members
}
Note: Java supports single inheritance—a class can extend only one direct superclass.
3. Example: Basic Inheritance
// Superclass
class Animal {
String name;
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + " is eating.");
}
}
// Subclass
class Dog extends Animal {
public Dog(String name) {
super(name); // Call superclass constructor
}
public void bark() {
System.out.println(name + " is barking.");
}
}
// Usage
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog("Buddy");
myDog.eat(); // Inherited from Animal
myDog.bark(); // Defined in Dog
}
}
Output:
Buddy is eating.
Buddy is barking.
4. The super Keyword
The super keyword is used to refer to the immediate parent class. It has three main uses:
A. Calling Superclass Constructor
public Dog(String name) {
super(name); // Must be the first statement
}
Rule: If the superclass has no no-argument constructor, the subclass must explicitly call a superclass constructor using
super().
B. Accessing Superclass Members
If a subclass overrides a method or hides a field, super can access the parent version.
class Animal {
protected String sound = "Generic sound";
public void makeSound() {
System.out.println(sound);
}
}
class Cat extends Animal {
private String sound = "Meow"; // Hides superclass field
public void makeSound() {
System.out.println(sound); // "Meow"
System.out.println(super.sound); // "Generic sound"
}
}
5. Method Overriding
A subclass can provide a specific implementation of a method already defined in its superclass. This is called method overriding.
Rules for Overriding
- The method name, return type, and parameter list must be identical.
- The access modifier cannot be more restrictive (e.g., cannot override a
publicmethod withprivate). - The
@Overrideannotation is optional but recommended for clarity and compile-time checking.
class Vehicle {
public void start() {
System.out.println("Vehicle started.");
}
}
class Car extends Vehicle {
@Override
public void start() {
System.out.println("Car engine started with key.");
}
}
6. Constructor Chaining in Inheritance
When an object of a subclass is created:
- The subclass constructor is called.
- It immediately calls the superclass constructor (explicitly with
super()or implicitly). - This continues up the inheritance chain to
java.lang.Object(the root of all classes).
class A {
A() { System.out.println("A constructor"); }
}
class B extends A {
B() { System.out.println("B constructor"); }
}
class C extends B {
C() { System.out.println("C constructor"); }
}
// Creating new C() outputs:
// A constructor
// B constructor
// C constructor
Note: If no
super()call is written, Java insertssuper()automatically—but only if the superclass has a no-argument constructor.
7. Inheritance and Access Control
A subclass inherits:
- All public and protected members (fields and methods) of the superclass.
- Package-private members, but only if the subclass is in the same package.
- Never inherits private members (though they exist in the object, they are inaccessible).
Example
class Parent {
private int secret = 100; // Not inherited
protected int visible = 200; // Inherited
public void show() { ... } // Inherited
}
8. The Object Class
In Java, every class implicitly extends java.lang.Object if no explicit superclass is declared. Thus, all objects inherit methods like:
toString()equals(Object obj)hashCode()getClass()clone()finalize()
Best Practice: Override
toString(),equals(), andhashCode()in meaningful classes.
9. Limitations of Inheritance
- Single Inheritance Only: Java does not allow a class to extend multiple classes (to avoid the "diamond problem").
- Tight Coupling: Subclasses depend on superclass implementation, which can reduce flexibility.
- Fragile Base Class Problem: Changes in the superclass can unintentionally break subclasses.
Alternative: Use composition ("has-a" relationship) when inheritance is not appropriate.
10. Best Practices
- Favor composition over inheritance when there is no true "is-a" relationship.
- Use inheritance for true specialization (e.g.,
SavingsAccountis anAccount). - Keep superclasses general and stable.
- Document intended extensibility—not all classes are designed to be subclassed.
- Prefer
protectedoverpublicfor members meant for subclass use. - Always call
super()explicitly when needed for clarity.
Conclusion
Inheritance is a powerful mechanism in Java that enables code reuse and logical class hierarchies. By allowing subclasses to inherit and extend the functionality of superclasses, it supports the creation of organized, scalable, and maintainable codebases. However, it must be used judiciously—only when a clear "is-a" relationship exists—and with awareness of its limitations. When combined with other OOP principles like encapsulation and polymorphism, inheritance forms the backbone of robust object-oriented design in Java. Mastering basic inheritance is a critical step toward advanced topics such as polymorphism, abstract classes, and interfaces.