Inheritance

Inheritance lets one class build on another. A SavingsAccount is a kind of Account: it has everything an account has, plus interest. The new class (subclass) inherits fields and methods from the existing one (superclass), adds its own, and can change inherited behaviour.

extends

JAVA
class Animal {
    String name;

    Animal(String name) {
        this.name = name;
    }

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

class Dog extends Animal {
    Dog(String name) {
        super(name);
    }

    void fetch() {
        System.out.println(name + " fetches the ball");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog rex = new Dog("Rex");
        rex.eat();
        rex.fetch();
    }
}
Output
Rex is eating
Rex fetches the ball

Dog extends Animal: a Dog has the name field and eat method from Animal, plus its own fetch. A class can extend only one class.

super(…) in constructors

A subclass constructor must first initialise the superclass part of the object by calling super(…). If you don't write it, Java inserts super() — which fails to compile when the superclass has no no-argument constructor:

JAVA
class Vehicle {
    final String plate;
    Vehicle(String plate) { this.plate = plate; }
}

class Car extends Vehicle {
    Car() {
    }
}

public class Main {
    public static void main(String[] args) {
    }
}
Compiler error
Main.java:7: error: constructor Vehicle in class Vehicle cannot be applied to given types;

Overriding methods

JAVA
class Account {
    protected double balance;

    Account(double balance) { this.balance = balance; }

    double monthlyFee() {
        return 2.0;
    }

    void endOfMonth() {
        balance -= monthlyFee();
    }
}

class StudentAccount extends Account {
    StudentAccount(double balance) { super(balance); }

    @Override
    double monthlyFee() {
        return 0.0;
    }
}

public class Main {
    public static void main(String[] args) {
        Account regular = new Account(100);
        Account student = new StudentAccount(100);
        regular.endOfMonth();
        student.endOfMonth();
        System.out.println(regular.balance + " / " + student.balance);
    }
}
Output
98.0 / 100.0

A subclass can override a method by declaring one with the same signature. endOfMonth, inherited unchanged, calls whichever monthlyFee belongs to the actual object. @Override asks the compiler to check that you really are overriding something — it catches typos like monthlyfee.

Calling the parent's version

JAVA
class Employee {
    String name;
    double salary;

    Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    String describe() {
        return name + " earns " + salary;
    }
}

class Manager extends Employee {
    int reports;

    Manager(String name, double salary, int reports) {
        super(name, salary);
        this.reports = reports;
    }

    @Override
    String describe() {
        return super.describe() + " and manages " + reports + " people";
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println(new Manager("Mei", 98000, 3).describe());
    }
}
Output
Mei earns 98000.0 and manages 3 people

super.method() calls the superclass's version, so an override can extend behaviour rather than replace it.

protected

protected members are visible to subclasses (and the same package). It's handy for things subclasses legitimately need, but it exposes internals to every subclass — keep fields private and offer protected methods when you can.

final classes and methods

JAVA
final class Money {
}

class FakeMoney extends Money {
}

public class Main {
    public static void main(String[] args) {
    }
}
Compiler error
Main.java:4: error: cannot inherit from final Money

A final class can't be extended (String is final), and a final method can't be overridden. Use it to protect classes whose behaviour must not change.

Every class extends Object

A class without extends implicitly extends java.lang.Object, the root of the class hierarchy. That's where toString, equals and hashCode come from (lesson 35).

Inheritance or composition?

Use inheritance only for genuine "is-a" relationships where the subclass can be used anywhere the superclass is expected. For "has-a" relationships — a car has an engine — store an object in a field instead (composition). Deep inheritance trees make code rigid; composition and interfaces (lesson 31) are usually more flexible.

Try it yourself

Create shapes that inherit a describe method but provide their own area.

Try it yourself · Main.java
Edit the code, copy it into Main.java and run java Main.java (Java 25+). How to set up Java
Output
circle with area 12.57
square with area 9.00