Skip to content
Theory · Inheritance and polymorphism · lesson 1 of 10

Inheritance

What you'll learn

What you'll learn:

  • declare a subclass with extends and call the parent's constructor with super(…);
  • predict whose method the call a.sound() runs, and tell overriding from overloading;
  • explain what the words abstract and final do for a class and a method;
  • cast a reference to a subclass type and check an object's type with instanceof.

Picture a TV and its remote. The remote has two buttons: "On" and "Volume". A year later the company releases a new model. It does everything the old one did, and it also records shows. The new model is not designed from scratch: the engineers take the old one and add one feature.

That is why the old remote works with the new TV too. The new model understands every one of its buttons: everything the old model had is still there.

Inheritance in Java works the same way: a new class gets the fields and methods of an existing class and adds its own.

Why is this useful? Say a program has dogs and cats, and both of them eat. Without inheritance, the eat method would have to be written in both classes, and a bug found in it would have to be fixed twice. With inheritance, the shared part is written once, in a class Animal:

JAVA
public class Main {
    public static void main(String[] args) {
        Dog d = new Dog();
        d.eat();  // eats
        d.bark(); // Woof
    }
}

class Animal {
    void eat() { System.out.println("eats"); }
}

class Dog extends Animal {
    void bark() { System.out.println("Woof"); }
}

Let's walk through the program step by step:

  1. The class Animal describes what every animal can do: the method eat. Its body is written on one line here to keep the example short.
  2. class Dog extends Animal declares the class Dog a subclass of Animal. The word extends means what it says: Dog extends Animal.
  3. Dog itself contains only the method bark.
  4. new Dog() builds a dog, and d.eat() prints eats: the dog got this method from Animal.
  5. d.bark() prints Woof: this is Dog's own method.

Parent and child

Inheritance is a way to declare a new class based on an existing one: the new class gets the fields and methods of the old one. The class being inherited from is called the superclass, or parent, and the new class the subclass, or child. Here Animal is the superclass and Dog the subclass.

Inheritance describes an "is a" relationship: a dog is an animal. That is why everything an Animal can do, a Dog can do too. The reverse is not true: Animal has no bark method.

What a subclass gets and what it does not:

  • it gets the parent's fields and methods: a Dog object uses them as its own;
  • the parent's private fields and methods are visible only inside the parent: if Dog touches the private field name of Animal, the compiler answers name has private access in Animal;
  • constructors are not inherited: every class has its own.

The parent's constructor: super(…)

A dog is an animal plus something of its own. So when a Dog object is built, the part that Animal describes has to be set up first. If Animal has a constructor with a parameter, the subclass calls it with the word super:

JAVA
public class Main {
    public static void main(String[] args) {
        Dog d = new Dog("Rex");
        System.out.println(d.name); // Rex
    }
}

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

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

Step by step:

  1. new Dog("Rex") calls the Dog constructor with the argument "Rex".
  2. The first statement of that constructor, super(name), calls the Animal constructor and passes it "Rex".
  3. The Animal constructor stores the name in the field name, and control returns to the Dog constructor.
  4. d.name prints Rex: the field is declared in Animal and filled in through super.

These are the rules for super(…):

  • it is written as the first statement of a constructor, like this(…); Java 25 allows some statements before it, but the course's code also compiles on Java 21;
  • if you do not write super(…), the compiler inserts super() at the start of the constructor, a call to the parent's constructor with no arguments;
  • so the parent's constructor always finishes before the subclass code after super(…) runs.

Interviewers often ask about the order in which constructors run. The answer: top down, from the most distant parent to the subclass.

One parent and the class Object

A Java class has exactly one parent: class Dog extends Animal, Pet does not compile. The chain can be long, though: a class Puppy extends Dog gets everything from both Dog and Animal.

And if you write no extends, the parent is the class Object. It sits at the root of all classes: every class is its subclass, directly or through a chain. That is why every object has the methods of Object, such as toString.

Here the TV picture is off. Engineers can build a new model from parts of two older ones, but a Java class always has one parent.

Common mistake

The parent needs an argument, and the subclass did not call super(…):

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

class Dog extends Animal {
    Dog(String name) { } // ✗
}
TEXT
error: constructor Animal in class Animal cannot be applied to given types;

The program does not compile. Since super(…) is missing, the compiler inserted super() with no arguments, and Animal has no such constructor: it has only the one that takes a String. It is the same message you get from new without the arguments a constructor needs. Call the parent's constructor yourself: Dog(String name) { super(name); }.

Key points

  • class Dog extends Animal declares a subclass: Dog gets the fields and methods of Animal and adds its own.
  • The parent's private members are not visible to the subclass, and constructors are not inherited.
  • super(…) calls the parent's constructor; without it the compiler inserts super(), and the parent's constructor finishes before the subclass code runs.
  • A class has exactly one parent, and Object sits at the root of all classes.