SyntaxStudy
Sign Up
Java Extending Classes and the super Keyword
Java Beginner 1 min read

Extending Classes and the super Keyword

Inheritance allows a class (subclass) to acquire the fields and methods of another class (superclass) using the extends keyword. Java supports single inheritance: a class can extend exactly one superclass. If no superclass is specified, the class implicitly extends Object. Inheritance models an "is-a" relationship; a Dog is an Animal, a SavingsAccount is a BankAccount. The super keyword has two uses in subclasses. super(...) calls the superclass constructor and must be the first statement in a subclass constructor. super.method() calls the superclass version of an overridden method, allowing the subclass to extend rather than completely replace the behaviour. If you do not explicitly call super(...), the compiler inserts a call to the no-argument superclass constructor, which fails if no such constructor exists. Method overriding lets a subclass provide a different implementation of a method inherited from a parent class. The @Override annotation instructs the compiler to verify that the method actually overrides a parent method, catching typos. The overriding method must have the same signature as the overridden method, a return type that is the same or a covariant (subtype), and an access modifier that is at least as permissive.
Example
// Superclass
class Animal {
    private final String name;
    private final int    age;

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

    public String getName() { return name; }
    public int    getAge()  { return age;  }

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

    public void introduce() {
        System.out.printf("I am %s, age %d. I say: %s%n", name, age, speak());
    }
}

// Subclass
class Dog extends Animal {
    private final String breed;

    Dog(String name, int age, String breed) {
        super(name, age);      // must be first statement
        this.breed = breed;
    }

    @Override
    public String speak() { return "Woof!"; }

    @Override
    public void introduce() {
        super.introduce();     // reuse parent logic
        System.out.println("  Breed: " + breed);
    }
}

class Cat extends Animal {
    private boolean indoor;

    Cat(String name, int age, boolean indoor) {
        super(name, age);
        this.indoor = indoor;
    }

    @Override public String speak() { return indoor ? "Meow~" : "MEOW!"; }
}

public class InheritanceDemo {
    public static void main(String[] args) {
        Animal[] animals = {
            new Dog("Rex",   3, "German Shepherd"),
            new Cat("Misty", 5, true),
            new Cat("Tiger", 2, false)
        };
        for (Animal a : animals) {
            a.introduce();
        }

        // instanceof check before downcast
        for (Animal a : animals) {
            if (a instanceof Dog d) {          // pattern variable (Java 16+)
                System.out.println(d.getName() + " is a dog");
            }
        }
    }
}