Table of Contents
- Introduction to Inheritance
- Types of Inheritance in Java
- The
extends
Keyword - Why Use Inheritance?
- The
super
Keyword- Accessing Parent Class Members
- Invoking Parent Class Constructor
- Method Overriding in Inheritance
- Inheritance with Constructors
- Hierarchical vs Multilevel Inheritance
- Composition vs Inheritance
- Common Pitfalls and Best Practices
- Summary
1. Introduction to Inheritance
Inheritance is one of the four fundamental principles of Object-Oriented Programming (OOP), alongside encapsulation, abstraction, and polymorphism. It allows a class (child or subclass) to inherit fields and methods from another class (parent or superclass), promoting code reuse and establishing a logical hierarchy between classes.
For example, if we have a class Vehicle
, we can create child classes like Car
, Bike
, and Truck
that inherit the general behavior of Vehicle
.
2. Types of Inheritance in Java
Java supports the following types of inheritance:
- Single Inheritance: One class inherits from another.
- Multilevel Inheritance: A class inherits from a derived class.
- Hierarchical Inheritance: Multiple classes inherit from a single parent class.
Java does not support multiple inheritance with classes to avoid ambiguity, but this can be achieved using interfaces.
3. The extends
Keyword
To inherit from a class in Java, the extends
keyword is used.
class Animal {
void eat() {
System.out.println("This animal eats food");
}
}
class Dog extends Animal {
void bark() {
System.out.println("Dog barks");
}
}
Here, Dog
inherits the method eat()
from Animal
.
4. Why Use Inheritance?
- Code Reusability: Write common logic once and reuse it across subclasses.
- Logical Hierarchy: Reflect real-world relationships (e.g.,
Dog
is-anAnimal
). - Method Overriding: Customize behavior in child classes.
- Maintenance: Easier to manage code in one place.
5. The super
Keyword
The super
keyword refers to the immediate parent class and is used to:
- Access parent class methods and variables
- Call parent class constructor
a. Accessing Parent Class Members
class Animal {
String sound = "Generic Sound";
void displaySound() {
System.out.println("Animal Sound: " + sound);
}
}
class Cat extends Animal {
String sound = "Meow";
void displaySound() {
System.out.println("Cat Sound: " + sound);
System.out.println("Animal Sound: " + super.sound); // Accessing parent member
}
}
b. Invoking Parent Class Constructor
super()
is used to call the constructor of the parent class and must be the first statement in the subclass constructor.
class Animal {
Animal() {
System.out.println("Animal constructor called");
}
}
class Dog extends Animal {
Dog() {
super(); // Calls Animal constructor
System.out.println("Dog constructor called");
}
}
This is especially useful when the parent class has a parameterized constructor.
6. Method Overriding in Inheritance
When a child class defines a method with the same signature as one in its parent class, it overrides the parent method.
class Animal {
void sound() {
System.out.println("Animal makes a sound");
}
}
class Lion extends Animal {
@Override
void sound() {
System.out.println("Lion roars");
}
}
Using super
to Access Overridden Method
class Lion extends Animal {
@Override
void sound() {
super.sound(); // Calls parent class method
System.out.println("Lion roars");
}
}
7. Inheritance with Constructors
Constructors are not inherited, but they can be called using super()
.
class Animal {
Animal(String name) {
System.out.println("Animal name: " + name);
}
}
class Elephant extends Animal {
Elephant() {
super("Elephant"); // Calls parent constructor
System.out.println("Elephant constructor done");
}
}
If the parent class does not have a default (no-argument) constructor, the child class must explicitly call a parameterized one using super
.
8. Hierarchical vs Multilevel Inheritance
Hierarchical Inheritance
class Animal { }
class Cat extends Animal { }
class Dog extends Animal { }
class Cow extends Animal { }
Multiple classes share a single base class.
Multilevel Inheritance
class Animal { }
class Mammal extends Animal { }
class Human extends Mammal { }
Inheritance in a chain format—each level builds on the previous one.
9. Composition vs Inheritance
Sometimes, composition is preferred over inheritance, especially when the relationship is has-a rather than is-a.
- Inheritance:
Car
is-aVehicle
- Composition:
Car
has-anEngine
Composition increases flexibility, avoids tight coupling, and enhances code maintainability.
10. Common Pitfalls and Best Practices
Pitfalls
- Overusing inheritance can make the code rigid and hard to refactor.
- Failing to use
super()
when necessary in constructors. - Forgetting that private members are not accessible in subclasses.
- Confusing method overriding with method overloading.
Best Practices
- Prefer composition over inheritance unless
is-a
clearly applies. - Always mark overridden methods with
@Override
for clarity and compile-time checks. - Avoid deep inheritance hierarchies; use interfaces where applicable.
- Ensure constructors properly invoke parent constructors for initialization.
11. Summary
Inheritance in Java is a cornerstone of OOP that enables efficient code reuse and logical relationships between classes. The super
keyword enhances control over parent-child interactions, whether it’s accessing variables, methods, or constructors. When used wisely, inheritance can lead to elegant and maintainable designs, but it must be applied with clear intent and good understanding of when alternatives like composition are better suited.