Inheritance
intermediatePart of Core Java
Theory
Inheritance is a fundamental object-oriented concept where one class (the child or subclass) acquires the properties and behaviors of another class (the parent or superclass). This promotes code reuse and establishes a natural hierarchy.
The extends Keyword
To inherit from a class, use the extends keyword:
public class Animal {
protected String name;
public void eat() {
System.out.println(name + " is eating");
}
}
public class Dog extends Animal {
public void bark() {
System.out.println(name + " is barking");
}
}Now Dog has access to both eat() (inherited) and bark() (its own).
The super Keyword
super refers to the parent class. It is used to:
- Call the parent constructor
- Access parent methods that have been overridden
public class Vehicle {
protected String brand;
public Vehicle(String brand) {
this.brand = brand;
}
public void start() {
System.out.println("Vehicle starting...");
}
}
public class Car extends Vehicle {
private int doors;
public Car(String brand, int doors) {
super(brand); // Call parent constructor — must be first statement
this.doors = doors;
}
@Override
public void start() {
super.start(); // Call parent's version
System.out.println("Car with " + doors + " doors started");
}
}Method Overriding and @Override
Overriding is when a subclass provides its own implementation of a method defined in the parent class. The method must have the same signature (name and parameters).
The @Override annotation tells the compiler that you intend to override a method. It will produce an error if the method doesn't actually override a parent method:
public class Bird extends Animal {
@Override
public void eat() {
System.out.println("Bird pecks at food");
}
}Differences from overloading:
- Overloading: Same method name, different parameters (compile-time)
- Overriding: Same method signature, different implementation (runtime)
Types of Inheritance
Java supports three forms of inheritance:
Single Inheritance — one class extends one parent:
Animal → Mammal
Multilevel Inheritance — a chain of inheritance:
Animal → Mammal → Dog
Hierarchical Inheritance — multiple classes extend the same parent:
Animal → Dog
Animal → Cat
Animal → Bird
Multiple inheritance (one class extending multiple classes) is not supported in Java to avoid the diamond problem. Instead, Java uses interfaces for this purpose.
Abstract Classes and Methods
An abstract class cannot be instantiated. It may contain both concrete methods and abstract methods (methods without a body):
public abstract class Shape {
protected String color;
public Shape(String color) {
this.color = color;
}
// Concrete method
public String getColor() {
return color;
}
// Abstract method — must be implemented by subclasses
public abstract double getArea();
// Abstract method
public abstract double getPerimeter();
}
public class Circle extends Shape {
private double radius;
public Circle(String color, double radius) {
super(color);
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
@Override
public double getPerimeter() {
return 2 * Math.PI * radius;
}
}Any class with an abstract method must be declared abstract. Subclasses must implement all abstract methods unless they are also abstract.
The final Keyword
final can be applied to:
-
Classes: Cannot be extended
public final class Math { ... } // Cannot have subclasses -
Methods: Cannot be overridden
public final void display() { ... } -
Variables: Cannot be reassigned (constant)
final double PI = 3.14159;
The Object Class
Every class in Java implicitly extends java.lang.Object. Key methods inherited from Object:
toString()— returns string representationequals(Object obj)— checks object equalityhashCode()— returns a hash code for the objectgetClass()— returns the runtime class
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Person person = (Person) obj;
return age == person.age && name.equals(person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}Always override both equals() and hashCode() together — they have a contract where equal objects must have equal hash codes. Many collections (HashMap, HashSet) rely on this.
Practical Examples
Prefer composition over inheritance. If a relationship is "has-a" rather than "is-a", use composition (include the object as a field) instead of inheritance.
Exercises
Shape Hierarchy
Create an abstract Shape class with an abstract getArea() method. Create Circle and Rectangle subclasses that implement getArea(). Add a getDescription() method to Shape that prints the shape type and area.
Expected Output:
Creating a red circle (radius 5) and a blue rectangle (4x6). Both print their color and calculated area.Library Inheritance System
Create a base class LibraryItem with fields: id, title, year. Subclasses: Book (author, isbn), DVD (director, duration), Magazine (issueNumber, month). All subclasses should override toString().
Expected Output:
Book: F001: 1984 by George Orwell (1949)\nDVD: D001: Inception directed by Nolan (2010, 148min)\nMagazine: M001: NatGeo #245 March 2024Vehicle Rental System with Interfaces
Create an interface Rentable with methods rent() and returnVehicle(). Create an abstract Vehicle class and subclasses Car, Motorcycle, and Truck. Each implements Rentable. Track whether each vehicle is currently rented.
Expected Output:
A rental agency with 3 vehicles. Renting a car marks it as unavailable. Trying to rent it again shows an error. Returning it makes it available again.Mini Quiz
Mini Quiz
Mini Project
Mini Project: E-Commerce Product Catalog
Build a product catalog system using inheritance and interfaces. Create a base Product class, subclasses for different product types (Book, Electronics, Clothing), and interfaces for tax calculation and discount application.
Requirements:
Bonus Challenge
Add a ShoppingCart class that accepts any Product subclass. Calculate the total with all taxes and discounts applied.