What is Inheritance in Java?
Inheritance is a mechanism where one class (child/subclass) inherits the properties and methods of another class (parent/superclass). The keyword used for inheritance in Java is extends. This relationship promotes code reuse and logical organization of classes.
The class being inherited from is called the parent class or superclass, and the class that inherits is called the child class or subclass. Java supports single inheritance (one child can have only one direct parent) but allows multiple inheritance through interfaces.
Important Keywords in Inheritance
Used to inherit properties and methods from a parent class. Example: class Dog extends Animal { }
Used to refer to the immediate parent class object. Used to access parent class variables, methods, and constructors.
When a child class provides a specific implementation of a method that is already defined in its parent class.
Objectives of Inheritance
🔁 Code Reusability: The main objectives of using inheritance are to reduce code duplication by reusing existing code from parent classes.
📦 Organized Code: It helps organize code efficiently by establishing hierarchical relationships between classes.
🔄 Runtime Polymorphism: Enables method overriding and runtime polymorphism, where a parent reference can point to a child object.
Advantages of Inheritance
📝 Reduces Code Redundancy: Common code can be written once in the parent class and reused by multiple child classes.
🔧 Enhances Maintainability: Changes made in the parent class automatically propagate to all child classes, making maintenance easier.
🎭 Supports Method Overriding: Child classes can provide specific implementations of parent class methods, enabling runtime polymorphism.
🏗️ Promotes Extensibility: New features can be added to child classes without modifying existing parent class code.
For example, a Dog class can inherit from Animal class, reusing its eat() method while adding new behavior like bark(). Similarly, Cat can inherit from Animal and add meow().
Limitations of Inheritance
🔗 Tight Coupling: Inheritance leads to tight coupling between parent and child classes. Changes in the parent can break child classes.
📈 Increased Complexity: Improper use of inheritance can increase code complexity and make the system harder to understand.
🚫 Single Inheritance Restriction: Java does not support multiple class inheritance (a class cannot extend more than one class), which can be limiting in some designs.
🎯 Not Always Appropriate: Not all relationships fit an IS-A model; sometimes composition is a better choice than inheritance.
Types of Inheritance in Java
One child class inherits from one parent class. Example: class B extends A { }
A chain where class B inherits from class A, and class C inherits from class B. Example: A → B → C
Multiple child classes inherit from a single parent class. Example: B extends A, C extends A
Java does not support multiple class inheritance directly, but a class can implement multiple interfaces: class C implements A, B { }
Inheritance Example in Java
// Parent class
class Animal {
String name;
void eat() {
System.out.println(name + " is eating...");
}
void sleep() {
System.out.println(name + " is sleeping...");
}
}
// Single Inheritance - Child class
class Dog extends Animal {
void bark() {
System.out.println(name + " is barking...");
}
// Method overriding
@Override
void eat() {
System.out.println(name + " is eating dog food...");
}
}
// Hierarchical Inheritance - Another child class
class Cat extends Animal {
void meow() {
System.out.println(name + " is meowing...");
}
}
// Multilevel Inheritance
class Puppy extends Dog {
void play() {
System.out.println(name + " is playing...");
}
}
// Using super keyword example
class Vehicle {
String brand = "Generic Vehicle";
Vehicle() {
System.out.println("Vehicle constructor called");
}
void display() {
System.out.println("Brand: " + brand);
}
}
class Car extends Vehicle {
String brand = "Toyota";
Car() {
super(); // Calls parent class constructor
System.out.println("Car constructor called");
}
void display() {
super.display(); // Calls parent class display method
System.out.println("Car Brand: " + brand);
}
}
public class InheritanceDemo {
public static void main(String[] args) {
System.out.println("=== Dog Example ===");
Dog dog = new Dog();
dog.name = "Buddy";
dog.eat(); // Overridden method
dog.sleep(); // Inherited method
dog.bark(); // Child's own method
System.out.println("\n=== Cat Example ===");
Cat cat = new Cat();
cat.name = "Whiskers";
cat.eat(); // Inherited method
cat.meow(); // Child's own method
System.out.println("\n=== Puppy Example (Multilevel) ===");
Puppy puppy = new Puppy();
puppy.name = "Max";
puppy.eat(); // Inherited from Dog (overridden)
puppy.bark(); // Inherited from Dog
puppy.play(); // Puppy's own method
System.out.println("\n=== super Keyword Example ===");
Car car = new Car();
car.display();
}
}
Best Practices for Using Inheritance
Use inheritance only when there is a clear IS-A relationship between classes
Prefer composition over inheritance when the relationship is HAS-A
Keep parent classes general and child classes specific
Use the @Override annotation to indicate method overriding clearly
Mark classes as final to prevent inheritance if not designed for it
Avoid deep inheritance hierarchies; keep the depth to 2-3 levels maximum