🌱BeginnerObject-Oriented Programming

Inheritance

Reuse and extend existing classes using extends - build class hierarchies where child classes inherit fields and methods from parent classes.

Overview

Inheritance lets one class (the child or subclass) build on another (the parent or superclass). The child inherits all non-private fields and methods of the parent, and can add its own fields and methods or override inherited methods. Use inheritance to model "is-a" relationships: a Dog IS-A Animal, a Car IS-A Vehicle, a Manager IS-A Employee. This avoids duplicating shared logic across related classes. In Java, every class implicitly extends Object. A class can extend exactly one class (single inheritance). Use implements for multiple interfaces (covered in J039).

Key Points

  • •extends keyword: `class Dog extends Animal`
  • •Child inherits all non-private fields and methods from the parent
  • •Override a parent method by redefining it with the same signature in the child; use @Override annotation
  • •super.method() calls the parent class version of a method
  • •super(args) in a constructor calls the parent constructor - must be first statement
  • •Java supports single inheritance only - a class can extend one class
  • •Every class implicitly extends Object if no extends is specified
  • •instanceof checks whether an object is of a particular type

Examples

Basic inheritance and method override

class Animal {
    String name;

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

    void speak() {
        System.out.println(name + " makes a sound.");
    }

    void breathe() {
        System.out.println(name + " breathes.");
    }
}

class Dog extends Animal {
    String breed;

    Dog(String name, String breed) {
        super(name); // calls Animal(name)
        this.breed = breed;
    }

    @Override
    void speak() {
        System.out.println(name + " barks: Woof!");
    }

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

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

    @Override
    void speak() {
        System.out.println(name + " meows: Meow!");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog rex = new Dog("Rex", "Labrador");
        Cat kitty = new Cat("Kitty");

        rex.speak();   // Rex barks: Woof!
        rex.breathe(); // Rex breathes. (inherited)
        rex.fetch();   // Rex fetches the ball!

        kitty.speak(); // Kitty meows: Meow!
        kitty.breathe(); // Kitty breathes. (inherited)
    }
}

breathe() is defined once in Animal and automatically available in Dog and Cat without copying it.

super - calling parent constructor and parent methods

class Shape {
    String colour;

    Shape(String colour) {
        this.colour = colour;
    }

    String describe() {
        return "A " + colour + " shape";
    }
}

class Circle extends Shape {
    double radius;

    Circle(String colour, double radius) {
        super(colour); // calls Shape(colour)
        this.radius = radius;
    }

    @Override
    String describe() {
        return super.describe() + " (circle, r=" + radius + ")";
    }

    double area() {
        return Math.PI * radius * radius;
    }
}

public class Main {
    public static void main(String[] args) {
        Circle c = new Circle("red", 5.0);
        System.out.println(c.describe()); // A red shape (circle, r=5.0)
        System.out.printf("Area: %.2f%n", c.area());
    }
}

super.describe() runs the parent's describe() and the child appends its own info.

instanceof and polymorphism

public class Main {
    public static void main(String[] args) {
        Animal[] animals = {
            new Dog("Rex", "Lab"),
            new Cat("Kitty"),
            new Dog("Max", "Poodle")
        };

        for (Animal a : animals) {
            a.speak(); // calls Dog.speak() or Cat.speak() based on actual type
            if (a instanceof Dog) {
                Dog d = (Dog) a;
                d.fetch(); // can call Dog-specific method after casting
            }
        }
    }
}

A Dog reference can be stored in an Animal variable (upcasting). instanceof lets you check the actual type before downcasting.

Common Mistakes

  • Forgetting super(args) in the child constructor when the parent has no no-arg constructor - compile error
  • Overriding without @Override annotation - if you misspell the method name you create a new method instead of overriding
  • Calling super() after other statements in the constructor - super() must be first
  • Inheriting too deeply: 5+ levels of inheritance is usually a design smell; consider composition instead

Note

Before using inheritance, ask: "Is the child really a more specific version of the parent?" If the relationship is "has-a" rather than "is-a," use composition (a field) instead.

Exercises

Write Java code and click Run to execute it instantly. When your output looks correct, mark as done.

Loading editor…

Completed: 0 / 4 exercises

Knowledge Check

Question 1 of 4

What keyword creates an inheritance relationship in Java?