Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Inheritance

Inheritance lets you build a new class on top of an existing one. The new class gets the fields and methods of its parent and can add its own or change the inherited ones.

extends

A child class is declared with the extends keyword. The parent is called the superclass, and the child the subclass:

class Animal {
    String name;
 
    String describe() {
        return name + " is an animal";
    }
}
 
class Dog extends Animal {
    String bark() {
        return name + ": Woof!";
    }
}
 
void main() {
    Dog dog = new Dog();
    dog.name = "Rex";
    IO.println(dog.describe());
    IO.println(dog.bark());
}

Output:

Rex is an animal
Rex: Woof!

Dog has no name field or describe() method of its own — they come from Animal.

The constructor and super(...)

Constructors are not inherited. A subclass constructor calls the parent constructor with super(...), passing it the data it needs:

class Animal {
    protected String name;
 
    Animal(String name) {
        this.name = name;
    }
}
 
class Cat extends Animal {
    Cat(String name) {
        super(name);
    }
 
    String meow() {
        return name + ": Meow";
    }
}
 
void main() {
    IO.println(new Cat("Kitty").meow());
}

Output:

Kitty: Meow

The protected modifier opens a field to subclasses and to classes in the same package, but not to the rest of the code. Packages are covered at the end of the chapter.

Overriding methods

A subclass may declare a method with the same signature as the parent's — then its version is the one that gets called. This is called overriding. The @Override annotation asks the compiler to check that the parent really has such a method:

class Animal {
    String sound() {
        return "...";
    }
}
 
class Dog extends Animal {
    @Override
    String sound() {
        return "Woof";
    }
}
 
void main() {
    IO.println(new Animal().sound());
    IO.println(new Dog().sound());
}

Output:

...
Woof

Calling the parent's version

With super.method() a subclass calls the parent's version of a method and extends it instead of rewriting everything:

class Product {
    String label() {
        return "Product";
    }
}
 
class Book extends Product {
    @Override
    String label() {
        return super.label() + " / Book";
    }
}
 
void main() {
    IO.println(new Book().label());
}

Output:

Product / Book

One parent and the Object class

In Java a class can have only one direct parent. If extends is not written, the parent is the Object class — the root of the whole hierarchy. That is why every object has the toString() and equals() methods: they are inherited from Object. A class marked final forbids inheriting from it — String is built this way, for example.

Common mistake

If the parent has only a constructor with parameters, the subclass must call it with super(...). Without that, Java tries to call a constructor without parameters, which does not exist:

class Animal {
    String name;
 
    Animal(String name) {
        this.name = name;
    }
}
 
class Dog extends Animal {
    Dog() {
        IO.println("Creating a dog");
    }
}
 
void main() {
    new Dog();
}

Output:

Main.java:10: error: constructor Animal in class Main.Animal cannot be applied to given types;
    Dog() {
          ^

Add super("Rex"); or pass the name through a parameter of the Dog constructor.

Thanks for reading!

Donate to the site — we work hard for you.