Java Inheritance and Polymorphism

Java inheritance lets one class reuse and extend another. The subclass (child) gets the fields and methods of the superclass (parent) and can add its own or change inherited behaviour.

extends and super

Use extends to inherit. Inside the child constructor, super(...) calls the parent constructor, and it must be the first statement.

class Vehicle {
    protected String brand;

    Vehicle(String brand) {
        this.brand = brand;
    }

    void describe() {
        System.out.println("A vehicle made by " + brand);
    }
}

class Car extends Vehicle {
    private final int doors;

    Car(String brand, int doors) {
        super(brand);
        this.doors = doors;
    }

    void honk() {
        System.out.println(brand + " car goes beep!");
    }
}

public class Main {
    public static void main(String[] args) {
        Car car = new Car("Toyota", 4);
        car.describe(); // inherited
        car.honk();     // own method
    }
}
A vehicle made by Toyota
Toyota car goes beep!

Method Overriding

A subclass can replace an inherited method by declaring one with the same signature. The @Override annotation asks the compiler to check that you really are overriding something. super.method() calls the parent version.

class Animal {
    String sound() { return "..."; }
}

class Cat extends Animal {
    @Override
    String sound() { return "Meow"; }
}

class Kitten extends Cat {
    @Override
    String sound() { return super.sound() + " (tiny)"; }
}

public class Main {
    public static void main(String[] args) {
        System.out.println(new Animal().sound());
        System.out.println(new Cat().sound());
        System.out.println(new Kitten().sound());
    }
}
...
Meow
Meow (tiny)

Polymorphism

A variable of a parent type can hold any subclass object. When you call a method, Java runs the version belonging to the actual object at runtime. This lets one piece of code work with many types.

class Shape {
    double area() { return 0; }
}

class Circle extends Shape {
    private final double r;
    Circle(double r) { this.r = r; }
    @Override double area() { return Math.PI * r * r; }
}

class Square extends Shape {
    private final double side;
    Square(double side) { this.side = side; }
    @Override double area() { return side * side; }
}

public class Main {
    public static void main(String[] args) {
        Shape[] shapes = { new Circle(1), new Square(3) };
        for (Shape s : shapes) {
            System.out.printf("%s: %.2f%n", s.getClass().getSimpleName(), s.area());
        }
    }
}
Circle: 3.14
Square: 9.00

instanceof with Pattern Matching

To check an object's real type and use it, Java 16+ lets you declare a variable right in the instanceof test, so no separate cast is needed.

public class Main {
    public static void main(String[] args) {
        Object value = "polymorphism";
        if (value instanceof String text && text.length() > 5) {
            System.out.println("Long string: " + text.toUpperCase());
        }
    }
}
Long string: POLYMORPHISM

Rules to Remember

  • A class can extend only one class (single inheritance).
  • Every class ultimately extends java.lang.Object.
  • A final class cannot be extended, and a final method cannot be overridden.
  • Private members are not visible to subclasses; use protected or getters.
  • Prefer composition (having an object as a field) when "is a" does not truly fit.

Frequently asked questions

What is the difference between overloading and overriding in Java?

Overloading means several methods with the same name but different parameters in one class, chosen at compile time. Overriding means a subclass replaces a parent method with the same signature, chosen at runtime.

Does Java support multiple inheritance?

Not for classes; a class can extend only one class. A class can, however, implement many interfaces.

What does super do in Java?

super calls the parent class constructor with super(...) or accesses parent methods and fields with super.name, which is useful inside an overriding method.