All Posts
Spring BootPart 6 of java-basics-to-advanced

OOP #2 — Inheritance, Interfaces & Polymorphism

Extend classes, implement interfaces, and write code that works with types it's never seen. The core of flexible Java design.

R
by Rupa
Jan 30, 20255 min read

Inheritance — Extending a Class

public class Animal {
    protected String name;
    protected int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void eat() {
        System.out.println(name + " is eating");
    }

    public String describe() {
        return name + " (age " + age + ")";
    }
}

public class Dog extends Animal {
    private String breed;

    public Dog(String name, int age, String breed) {
        super(name, age);  // call parent constructor — must be first line
        this.breed = breed;
    }

    public void bark() {
        System.out.println(name + " says: Woof!");
    }

    @Override
    public String describe() {
        return super.describe() + ", breed: " + breed;
    }
}
Dog dog = new Dog("Rex", 3, "Labrador");
dog.eat();        // Rex is eating (inherited)
dog.bark();       // Rex says: Woof!
dog.describe();   // Rex (age 3), breed: Labrador
@Override is not optional — use it

@Override tells the compiler you intend to override a parent method. Without it, a typo in the method name silently creates a new method instead of overriding. Always use it.

The final Keyword on Classes and Methods

public final class ImmutableValue { }  // can't be extended

public class Base {
    public final void criticalMethod() { }  // can't be overridden
}

Abstract Classes

An abstract class can't be instantiated — it's a partial implementation meant to be extended:

public abstract class Shape {
    private String color;

    public Shape(String color) { this.color = color; }

    // Concrete method — shared by all shapes
    public String getColor() { return color; }

    // Abstract method — each shape must implement this
    public abstract double area();
    public abstract double perimeter();
}

public class Circle extends Shape {
    private double radius;

    public Circle(String color, double radius) {
        super(color);
        this.radius = radius;
    }

    @Override public double area()      { return Math.PI * radius * radius; }
    @Override public double perimeter() { return 2 * Math.PI * radius; }
}

public class Rectangle extends Shape {
    private double w, h;

    public Rectangle(String color, double w, double h) {
        super(color);
        this.w = w;
        this.h = h;
    }

    @Override public double area()      { return w * h; }
    @Override public double perimeter() { return 2 * (w + h); }
}

Interfaces — Define a Contract

An interface says "any class that implements me must have these methods":

public interface Drawable {
    void draw();  // implicitly public abstract
    
    // Default method — has a body, can be overridden
    default String getDrawInfo() {
        return "Drawable object";
    }
}

public interface Resizable {
    void resize(double factor);
}

// A class can implement multiple interfaces
public class Canvas implements Drawable, Resizable {
    @Override
    public void draw() { System.out.println("Drawing on canvas"); }

    @Override
    public void resize(double factor) { System.out.println("Resizing by " + factor); }
}
Abstract class vs Interface

Use an abstract class when subclasses share state (fields) or base behaviour. Use an interface to define a capability contract that unrelated classes can fulfil. A class can only extend one class but implement many interfaces.

Polymorphism — One Variable, Many Types

// The variable type is Shape, but the object can be any subclass
Shape s1 = new Circle("red", 5);
Shape s2 = new Rectangle("blue", 4, 6);

// Both call area() — but the RIGHT version for each type
System.out.println(s1.area());  // 78.53... (Circle's area)
System.out.println(s2.area());  // 24.0 (Rectangle's area)

// Works in collections too
List<Shape> shapes = List.of(new Circle("red", 3), new Rectangle("blue", 4, 5));
for (Shape shape : shapes) {
    System.out.println(shape.area());  // calls the right area() for each
}

instanceof and Pattern Matching (Java 16+)

// Old way — verbose and repetitive
if (shape instanceof Circle) {
    Circle c = (Circle) shape;
    System.out.println(c.getRadius());
}

// New way — pattern matching (Java 16+)
if (shape instanceof Circle c) {
    System.out.println(c.getRadius());  // c is already cast and ready
}

// Pattern matching in switch (Java 21)
String info = switch (shape) {
    case Circle c    -> "Circle with radius " + c.getRadius();
    case Rectangle r -> "Rectangle " + r.getW() + "x" + r.getH();
    default          -> "Unknown shape";
};

Sealed Classes — Controlled Hierarchies (Java 17+)

Sealed classes restrict which classes can extend them:

public sealed class Result<T> permits Success, Failure {
    // ...
}

public final class Success<T> extends Result<T> {
    private final T value;
    public Success(T value) { this.value = value; }
    public T getValue() { return value; }
}

public final class Failure<T> extends Result<T> {
    private final String error;
    public Failure(String error) { this.error = error; }
    public String getError() { return error; }
}

// Now switch is exhaustive — compiler knows all subtypes
String msg = switch (result) {
    case Success<String> s -> "Got: " + s.getValue();
    case Failure<String> f -> "Error: " + f.getError();
    // no default needed — sealed covers all cases
};
Favour interfaces over inheritance

Deep inheritance hierarchies become tangled quickly. In modern Java, prefer implementing interfaces + composition over extending classes. This is the "favour composition over inheritance" principle.

What's Next?

Collections & Streams #1 covers the Java Collections Framework — List, Set, Map, and how to choose the right one. This is where you'll spend most of your day-to-day Java time.

#java#oop#inheritance#interfaces#polymorphism

✦ Enjoyed this post?

Get posts like this in your inbox

No spam, just real tutorials when they're ready.

Discussion

Powered by GitHub

Comments use GitHub Discussions — no separate account needed if you have GitHub.