Kestrel Exams kestrel logo KESTREL EXAMSPRACTICE TO PASS
Java14 min readCode verified

Inheritance: extends, super, and overriding a method

Inheritance lets one class start from another and change only what is different. This guide covers the three names for the two classes, what extends really hands down, the super call every subclass constructor makes, and how overriding differs from overloading. Every listing was compiled and run on OpenJDK 21.

Practice this topic in the free app →All Java guides

A family recipe card#

Picture your grandmother’s chili recipe on an index card. You like it, but you make it with turkey and add corn. You do not rewrite the whole card. You clip a note to it that says “same as Grandma’s, except: turkey instead of beef, and add corn at the end”.

That note is a subclass. Grandma’s card is the superclass. Inheritance just means a new class starts with everything an existing class has, and then adds or changes a few things. You write only the differences.

Your course, your textbook and your exam use three different pairs of names for the same two roles. They mean exactly the same thing:

The class you start fromThe class that starts from it
base classderived class
parent classchild class
superclasssubclass

The test for whether inheritance fits is one sentence: a subclass object is a superclass object. A dog is a pet. A savings account is a bank account. If the sentence sounds silly (“an engine is a car”), inheritance is the wrong tool. The polymorphism guide comes back to this test.

extends: what the child gets for free#

The keyword is extends. Write it after the class name, followed by the parent:

class Pet {
    private String name;

    public Pet(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

class Dog extends Pet {
    public Dog(String name) {
        super(name);
    }

    public String fetch() {
        return getName() + " brings the ball back";
    }
}

public class Extends {
    public static void main(String[] args) {
        Dog rex = new Dog("Rex");
        System.out.println(rex.getName());
        System.out.println(rex.fetch());
    }
}
Rex
Rex brings the ball back

Dog never wrote getName, yet rex.getName() works. The child received the parent’s public methods. It also added one of its own, fetch. The parent did not get fetch: inheritance only flows downwards, like the recipe note that Grandma’s card knows nothing about.

To keep each listing short, the classes in this guide share one file, and only the class with main is public. In your own projects, give each public class its own .java file, named after the class.

A Java class can extend only one parent. class Dog extends Pet, Animal does not compile. (Interfaces, two guides on, are how Java gets around this.)

Private fields stay private, even from children#

A subclass object does contain the parent’s private fields, but the subclass’s own code is not allowed to touch them by name. private means “only code inside this one class”, and a child is a different class. This is why the Java rulebook, and many exam questions, say that private members are not inherited: the data is there, but the child has no access to it.

class Pet {
    private String name;

    public Pet(String name) {
        this.name = name;
    }
}

class Dog extends Pet {
    public Dog(String name) {
        super(name);
    }

    public String tag() {
        return "Tag: " + name;
    }
}

public class PrivateErr {
    public static void main(String[] args) {
        System.out.println(new Dog("Rex").tag());
    }
}
PrivateErr.java:15: error: name has private access in Pet
        return "Tag: " + name;
                         ^
1 error

The fix is to go through the parent’s public methods, here getName(). If you want children (and only children) to reach a member directly, mark it protected. Most courses still prefer private fields with getters, because it keeps the parent in control of its own data.

ModifierWho can use it by nameUML symbol
privateonly the class itself-
protectedthe class, its subclasses, and classes in the same package#
publiceveryone+

Constructors and super(...)#

Constructors are never inherited. A Dog needs its own constructor. Its first job is to let the parent set up the parent’s part, by calling super(...) with the parent’s arguments. That call must be the first line of the child’s constructor. (Java 25 relaxed this a little, allowing simple checks before the call, but the first-line rule is what your textbook, your IDE on older versions, and your exam expect.)

If you leave the call out, Java quietly writes super(); for you, with no arguments. That works only when the parent has a constructor that takes no arguments. When it does not, you get this:

class Pet {
    private String name;

    public Pet(String name) {
        this.name = name;
    }
}

class Dog extends Pet {
    public Dog(String name) {
        System.out.println("Making a dog");
    }
}

public class NoSuper {
    public static void main(String[] args) {
        new Dog("Rex");
    }
}
NoSuper.java:10: error: constructor Pet in class Pet cannot be applied to given types;
    public Dog(String name) {
                            ^
  required: String
  found:    no arguments
  reason: actual and formal argument lists differ in length
1 error

Read the error as “you tried to build a Pet with nothing, but a Pet needs a String”. The fix is the explicit call: super(name);.

Because the parent is always set up first, constructors run from the top of the family down. Watch the order:

class Animal {
    public Animal() {
        System.out.println("1. Animal part built");
    }
}

class Dog extends Animal {
    public Dog() {
        super();
        System.out.println("2. Dog part built");
    }
}

class Puppy extends Dog {
    public Puppy() {
        System.out.println("3. Puppy part built");
    }
}

public class Chain {
    public static void main(String[] args) {
        new Puppy();
    }
}
1. Animal part built
2. Dog part built
3. Puppy part built

Building one Puppy ran three constructors, oldest ancestor first. A useful way to remember it: you cannot add a basement after the house is built. The parent part is the foundation, so it is poured first.

Overriding: replacing a parent method#

Overriding means the child writes its own version of a method the parent already has, with the same name and the same parameter list. When that method is called on a child object, the child’s version runs. This is the “turkey instead of beef” line on the recipe note.

class Pet {
    public String speak() {
        return "...";
    }
}

class Cat extends Pet {
    @Override
    public String speak() {
        return "Meow";
    }
}

class Parrot extends Pet {
    @Override
    public String speak() {
        return "Hello!";
    }
}

public class Overriding {
    public static void main(String[] args) {
        System.out.println(new Pet().speak());
        System.out.println(new Cat().speak());
        System.out.println(new Parrot().speak());
    }
}
...
Meow
Hello!

The cat and the parrot replaced speak. The generic pet still uses the parent’s version. Two rules come with overriding: the return type must match (or be a subclass of it), and the child cannot make the method more private. A public method stays public.

Put @Override on the line above every method you mean to override. It is an annotation, a note to the compiler, and it asks the compiler to check that a matching parent method really exists. Without it, a typo silently creates a brand-new method instead:

class Pet {
    public String speak() {
        return "...";
    }
}

class Cat extends Pet {
    @Override
    public String speek() {
        return "Meow";
    }
}

public class Typo {
    public static void main(String[] args) {
        System.out.println(new Cat().speak());
    }
}
Typo.java:8: error: method does not override or implement a method from a supertype
    @Override
    ^
1 error

That error is a gift. Without @Override, speek would compile, the cat would still say the generic line, and you would be hunting for the bug at run time.

Overriding versus overloading#

The two words differ by three letters and examiners love to swap them. The difference is the parameter list.

OverridingOverloading
Namesamesame
Parameter listsamedifferent (number, types or order)
Wherein a subclass, replacing the parent’s versionusually in the same class (a subclass can add one too)
Who picks the versionthe object, while the program runsthe compiler, from the argument types
class Animal {
    public String move() {
        return "moves";
    }
}

class Bird extends Animal {
    @Override
    public String move() {
        return "flies";
    }

    public String move(int metres) {
        return "flies " + metres + " m";
    }
}

public class Both {
    public static void main(String[] args) {
        Bird b = new Bird();
        System.out.println(new Animal().move());
        System.out.println(b.move());
        System.out.println(b.move(40));
    }
}
moves
flies
flies 40 m

Bird has three move methods. move() with no arguments replaces the parent’s, which is overriding. move(int) has a different parameter list, which is overloading: it sits beside the others rather than replacing anything. The memory line: override is a re-ride of the same route; overload loads a different set of parameters.

Calling the parent’s version with super.#

Sometimes you want to add to the parent’s behaviour rather than throw it away. Inside an overriding method, super.methodName() runs the parent’s version. The word super here means “my parent’s part of me”.

class Account {
    private String owner;
    private double balance;

    public Account(String owner, double balance) {
        this.owner = owner;
        this.balance = balance;
    }

    public String describe() {
        return owner + ": $" + balance;
    }
}

class Savings extends Account {
    private double rate;

    public Savings(String owner, double balance, double rate) {
        super(owner, balance);
        this.rate = rate;
    }

    @Override
    public String describe() {
        return super.describe() + " at " + rate + "%";
    }
}

public class SuperDot {
    public static void main(String[] args) {
        System.out.println(new Account("Ana", 120.0).describe());
        System.out.println(new Savings("Ben", 500.0, 2.5).describe());
    }
}
Ana: $120.0
Ben: $500.0 at 2.5%

Savings reused the parent’s description and tacked the rate on the end. Without the super. prefix, describe() would call itself, then call itself again, until the call stack ran out of room and Java stopped with a StackOverflowError. That is a classic exam trap.

So super has two jobs, and it is worth keeping them apart:

Written asWhereDoes
super(...)first line of a constructorruns the parent’s constructor
super.method()any instance methodruns the parent’s version of that method

Drawing inheritance in UML#

UML, the Unified Modeling Language, is a standard way to sketch classes as boxes. Each box has three parts stacked top to bottom: the class name, the fields, then the methods. A minus sign means private and a plus sign means public. Inheritance is drawn as a solid line with a hollow triangle arrowhead pointing at the parent.

        +-----------------------+
        |        Account        |
        +-----------------------+
        | - owner : String      |
        | - balance : double    |
        +-----------------------+
        | + deposit(amt:double) |
        | + describe() : String |
        +-----------------------+
                    ^   hollow triangle points at the parent
                    |
        +-----------------------+
        |        Savings        |
        +-----------------------+
        | - rate : double       |
        +-----------------------+
        | + describe() : String |
        +-----------------------+

The child box lists only what is new or overridden. Savings shows describe() again because it overrides it; it does not repeat deposit, which it simply inherits. If you remember one thing: the arrow points from child to parent, because the child knows who its parent is, and the parent does not know its children.

One more fact for later: a class with no extends still has a parent. Java gives it Object, the class at the top of every family tree. The next guide is about what you inherit from it.

One sentence to carry into the exam

A subclass is the recipe note, not a new card: it calls super(...) first, inherits everything public, and overrides a method only when the name and the parameter list match. Same parameters is overriding; different parameters is overloading.

Where these go wrong#

  • Reaching for a parent’s private field by name. It is there, but locked. Use the parent’s getter.
  • Putting super(...) anywhere but the first line. Before Java 25 it must come first, or the constructor does not compile; write it first and you are safe on every version.
  • Forgetting super(...) when the parent has no empty constructor. Java inserts super() for you, and it fails.
  • Calling an overloaded method an override. A different parameter list is a new method beside the old one, not a replacement.
  • Leaving off @Override. A misspelled name then compiles as a new method and the parent’s version keeps running.
  • Writing describe() instead of super.describe() inside an override. The method calls itself until the program crashes with a StackOverflowError.
  • Drawing the UML arrow at the child. The hollow triangle points at the parent.
  • Trying to extend two classes. Java allows one parent class.

Practice#

Answer each one on paper before you look at the solutions. Every answer that involves running code was checked by compiling and running it.

  1. In class Truck extends Vehicle, name the superclass and the subclass, and give the other two names for each.
  2. What does this program print?
    class A {
        public A() { System.out.println("A"); }
        public void show() { System.out.println("A.show"); }
    }
    class B extends A {
        public B() { System.out.println("B"); }
        @Override
        public void show() {
            super.show();
            System.out.println("B.show");
        }
    }
    // in main:
    B b = new B();
    b.show();
  3. A class Pet has only the constructor Pet(String name). Its subclass has public Dog() { }. Why does this not compile, and what is the smallest fix?
  4. Shape has double area(). Circle extends Shape declares double area() and also double area(int decimals). Which one overrides and which one overloads?
  5. Write a class Square that extends a Rectangle(double width, double height) class. A Square is built from one side length and overrides describe() to say “Square” instead of “Rectangle”.
  6. What does @Override do, and what happens if you leave it off a correctly spelled override?

Solutions#

  1. Vehicle is the superclass, also called the base class or parent class. Truck is the subclass, also called the derived class or child class. The test sentence holds: a truck is a vehicle.
  2. The parent constructor runs first (Java inserted super() at the top of B()), then show runs the parent’s version before adding its own line:
    class A {
        public A() {
            System.out.println("A");
        }
    
        public void show() {
            System.out.println("A.show");
        }
    }
    
    class B extends A {
        public B() {
            System.out.println("B");
        }
    
        @Override
        public void show() {
            super.show();
            System.out.println("B.show");
        }
    }
    
    public class Q2 {
        public static void main(String[] args) {
            B b = new B();
            b.show();
        }
    }
    A
    B
    A.show
    B.show
  3. Because Java inserts super(); as the first line of Dog(), and Pet has no constructor that takes no arguments. The compiler reports constructor Pet in class Pet cannot be applied to given types. Fix: make the first line pass a name up, for example super("unnamed");, or give Dog a String name parameter and call super(name);.
  4. area() in Circle has the same name and the same (empty) parameter list as the parent’s, so it overrides. area(int decimals) has a different parameter list, so it overloads: it adds a new method and replaces nothing.
  5. The constructor passes the side up twice, and describe is overridden with the same signature:
    class Rectangle {
        private double width, height;
    
        public Rectangle(double width, double height) {
            this.width = width;
            this.height = height;
        }
    
        public double area() {
            return width * height;
        }
    
        public String describe() {
            return "Rectangle with area " + area();
        }
    }
    
    class Square extends Rectangle {
        public Square(double side) {
            super(side, side);
        }
    
        @Override
        public String describe() {
            return "Square with area " + area();
        }
    }
    
    public class Q5 {
        public static void main(String[] args) {
            System.out.println(new Rectangle(2, 5).describe());
            System.out.println(new Square(3).describe());
        }
    }
    Rectangle with area 10.0
    Square with area 9.0
    Square never wrote area(); it inherited it.
  6. It asks the compiler to confirm that the method really overrides a parent method, and to stop with method does not override or implement a method from a supertype if it does not. Leaving it off a correctly spelled override changes nothing at run time; the method still overrides. You lose only the safety check against typos.

Test-readiness checklist#

These are the items from the course’s Exam 2 topic list that this guide covers. Tick each one only when you can do it without looking.

  • ☐  I can explain inheritance and give the three pairs of names: base/derived, parent/child, super/sub class.
  • ☐  I can write a subclass with extends and a constructor that calls super(...) first.
  • ☐  I can override a method, and I can say how overriding differs from overloading.
  • ☐  I can call the base class’s version of a method with super.method().
  • ☐  I can draw the UML for a parent and child class, arrow pointing the right way.

Test yourself in the free Kestrel Exams app

40 practice questions on extends, super, constructor chains and overriding, with every code answer checked by compiling and running it. Free, offline, no account.

Practise inheritance →

Frequently asked questions#

What is the difference between a superclass and a subclass in Java?

The superclass is the existing class; the subclass is the new class that extends it with the extends keyword. The subclass inherits the superclass's public and protected members, and adds or overrides only what is different. Superclass, base class and parent class all mean the same thing, as do subclass, derived class and child class.

Does a subclass inherit private fields?

A subclass object contains the parent's private fields, but the subclass's own code cannot use them by name. Code in the subclass gets "has private access" from the compiler. It must go through the parent's public methods such as getters, or the field must be made protected.

Why must super() be the first line of a constructor?

Because the parent part of the object has to be set up before the child part can rely on it. Java 25 relaxed the rule slightly to allow simple statements that do not use the object before the call, but on earlier versions, and in most courses, super(...) must come first. If you do not write a super call, Java inserts super() with no arguments, which fails to compile when the parent has no constructor that takes no arguments.

What is the difference between overriding and overloading?

Overriding is a subclass method with the same name and the same parameter list as a parent method; it replaces the parent version for objects of the subclass, and the version is chosen while the program runs. Overloading is a method with the same name but a different parameter list; it adds a new method, and the compiler chooses which one from the argument types.

What does super.method() do?

Inside a subclass, super.method() runs the parent's version of a method, usually from inside an override that wants to add to the parent's behaviour rather than replace it. Without the super. prefix, the override would call itself.

Can a Java class extend more than one class?

No. A Java class has exactly one direct superclass. If no extends clause is written, the superclass is Object. A class can implement many interfaces, which is how Java lets one class take on several roles.

Suggest a change

Something here not clear? A topic you wish we covered? Tell us. We read every message, and a request is the fastest way to get a guide written — several of these exist because somebody asked.