# Inheritance

Course: [Java](https://www.devtutorials.ai/learn/java) · Section: Object-Oriented Programming
Source: https://www.devtutorials.ai/learn/java/object-oriented-programming/inheritance

> Reuse code with inheritance: parent and child classes, the IS-A test, types of inheritance, extends, super and constructor chaining.

Think about a family.

A child gets many things from their parents: the family name, maybe eye colour, maybe a way of speaking. The child does not have to invent those traits from scratch. They come with the family.

But the child is also their own person. They learn new skills, and sometimes they do things differently from their parents.

In Java, a class can get fields and methods from another class in the same way. This is called inheritance.

In simple words: inheritance lets a new class reuse an existing class's code, then add to it or change it.

## What You Will Learn

In this lesson, you will learn:

1. What inheritance is, and the IS-A test for when to use it.
2. What parent (superclass) and child (subclass) classes are.
3. The types of inheritance Java supports.
4. How to use the `extends` keyword.
5. How the `super` keyword reaches the parent's methods and constructor.
6. How constructors run from parent to child.
7. How inheritance hierarchies are organised.

## Start With a Working Example

Press **Run**.

```java runnable title="Two child classes reuse the parent's code"
public class Main {
    public static void main(String[] args) {
        Car car = new Car("Maruti", 5);
        Bike bike = new Bike("Hero", true);

        car.start();
        car.showSeats();

        bike.start();
        bike.showGear();
    }
}

class Vehicle {
    String brand;

    Vehicle(String brand) {
        this.brand = brand;
    }

    void start() {
        System.out.println(brand + " is starting.");
    }
}

class Car extends Vehicle {
    int seats;

    Car(String brand, int seats) {
        super(brand);
        this.seats = seats;
    }

    void showSeats() {
        System.out.println(brand + " car has " + seats + " seats.");
    }
}

class Bike extends Vehicle {
    boolean hasGears;

    Bike(String brand, boolean hasGears) {
        super(brand);
        this.hasGears = hasGears;
    }

    void showGear() {
        System.out.println(brand + " bike has gears: " + hasGears);
    }
}
```

Expected output:

```text
Maruti is starting.
Maruti car has 5 seats.
Hero is starting.
Hero bike has gears: true
```

`start()` and `brand` are written once, in `Vehicle`. `Car` and `Bike` both get them for free. Each child then adds its own extra field and method.

### Try This

Add a method `void honk()` to `Vehicle` that prints `brand + " says beep!"`. Call `car.honk()` and `bike.honk()`. Both work, and you wrote `honk()` only once.

## Introduction to Inheritance

**Inheritance** means one class receives the fields and methods of another class.

Without inheritance, `Car`, `Bike` and `Bus` would each need their own copy of `brand` and `start()`. Fixing a bug in `start()` would mean fixing it in three places.

With inheritance, the shared code lives in one parent class. Each child class only adds what makes it different.

The benefits:

- **Less repeated code.** Shared fields and methods are written once.
- **Easier fixes.** A change in the parent reaches every child.
- **Clear structure.** The classes form a family tree that matches the real world.

## IS-A Relationship

Before using inheritance, ask one question: **"Is the child a kind of the parent?"**

- A car **is a** vehicle. ✓
- A dog **is an** animal. ✓
- A savings account **is a** bank account. ✓
- A car **is an** engine? ✗ A car **has an** engine.

If the IS-A sentence makes sense, inheritance fits. This is called the **IS-A relationship**.

If the sentence only works as "has a", use a field instead. A `Car` should **have** an `Engine` field, not extend `Engine`. This is called the **HAS-A relationship**, or **composition**.

| Relationship | Test sentence | Java tool | Example |
|---|---|---|---|
| IS-A | "A car is a vehicle" | Inheritance (`extends`) | `class Car extends Vehicle` |
| HAS-A | "A car has an engine" | A field | `class Car { Engine engine; }` |

## Parent and Child Classes

### Parent Class (Superclass)

The **parent class** is the class being inherited from. It is also called the **superclass** or **base class**.

It holds the fields and methods that all its children share.

### Child Class (Subclass)

The **child class** is the class that inherits. It is also called the **subclass** or **derived class**.

It gets the parent's members, and it can:

- **add** new fields and methods;
- **override** (replace) a parent method with its own version.

### Relationship Between Classes

The child knows about its parent. The parent does **not** know about its children.

So a `Car` can use everything a `Vehicle` has. But a `Vehicle` cannot use `seats`, because not every vehicle has seats.

### Reusing Existing Members

A child class inherits:

- `public` and `protected` fields and methods;
- default (no modifier) members, if the child is in the same package.

A child class does **not** inherit:

- `private` members. They exist inside the object, but the child cannot reach them directly by name;
- constructors. Each class has its own constructors. A child calls the parent's constructor with `super(...)`.

```java runnable title="The child reuses, adds and replaces"
public class Main {
    public static void main(String[] args) {
        Employee e = new Employee();
        Manager m = new Manager();

        e.work();
        m.work();
        m.holdMeeting();

        System.out.println("Manager's company: " + m.company);
    }
}

class Employee {
    String company = "Syntech";

    void work() {
        System.out.println("Employee is writing reports.");
    }
}

class Manager extends Employee {
    void work() {
        System.out.println("Manager is reviewing reports.");
    }

    void holdMeeting() {
        System.out.println("Manager is holding a meeting.");
    }
}
```

Expected output:

```text
Employee is writing reports.
Manager is reviewing reports.
Manager is holding a meeting.
Manager's company: Syntech
```

`Manager` **reuses** `company` without writing it. It **replaces** `work()` with its own version. It **adds** `holdMeeting()`, which a plain `Employee` does not have.

## Types of Inheritance

### Single

**Single inheritance** means one child extends one parent.

```text
Animal
  └── Dog
```

### Multilevel

**Multilevel inheritance** is a chain. A child becomes the parent of another class.

```text
Animal
  └── Dog
        └── Puppy
```

A `Puppy` gets everything from `Dog`, and `Dog` gets everything from `Animal`. So `Puppy` has the members of both.

### Hierarchical

**Hierarchical inheritance** means several children extend the same parent.

```text
        Vehicle
       /   |    \
    Car   Bike   Bus
```

The first example in this lesson was hierarchical: `Car` and `Bike` both extend `Vehicle`.

```java runnable title="Multilevel: each level adds one more ability"
public class Main {
    public static void main(String[] args) {
        Puppy p = new Puppy();
        p.eat();
        p.bark();
        p.play();
    }
}

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

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

class Puppy extends Dog {
    void play() {
        System.out.println("Playing with a ball.");
    }
}
```

Expected output:

```text
Eating food.
Barking: Woof!
Playing with a ball.
```

`Puppy` wrote only `play()`. It got `bark()` from `Dog` and `eat()` from `Animal`, two levels up.

### Multiple Inheritance Through Interfaces

**Multiple inheritance** means one class has more than one parent.

Java does **not** allow a class to extend two classes. `class C extends A, B` does not compile.

The reason is the **diamond problem**. If `A` and `B` both had a method `show()` with different bodies, which one should `C` get? Java avoids that problem.

But a class **can** implement many interfaces. That is how Java gives one class several "parents" safely.

```java runnable title="One parent class, two interfaces"
public class Main {
    public static void main(String[] args) {
        Duck d = new Duck();
        d.breathe();
        d.fly();
        d.swim();
    }
}

class Bird {
    void breathe() {
        System.out.println("Breathing air.");
    }
}

interface Flyer {
    void fly();
}

interface Swimmer {
    void swim();
}

class Duck extends Bird implements Flyer, Swimmer {
    public void fly() {
        System.out.println("Flying over the lake.");
    }

    public void swim() {
        System.out.println("Swimming in the lake.");
    }
}
```

Expected output:

```text
Breathing air.
Flying over the lake.
Swimming in the lake.
```

`Duck` **extends** one class, `Bird`, and **implements** two interfaces. `extends` always comes before `implements`.

### Hybrid Inheritance Through Interfaces

**Hybrid inheritance** mixes two or more of the types above. For example, a class might be part of a multilevel chain and also implement several interfaces.

```text
   Animal                Pet (interface)
     │                      │
    Dog ────────────────────┤
     │                      │
  GuideDog        Trainable (interface)
```

```java runnable title="A multilevel chain mixed with interfaces"
public class Main {
    public static void main(String[] args) {
        GuideDog g = new GuideDog("Bruno");
        g.eat();
        g.bark();
        g.cuddle();
        g.learn("Stop at the kerb");
        g.guide();
    }
}

interface Pet {
    void cuddle();
}

interface Trainable {
    void learn(String command);
}

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

class Dog extends Animal implements Pet {
    String name;

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

    void bark() {
        System.out.println(name + " barks.");
    }

    public void cuddle() {
        System.out.println(name + " wags its tail.");
    }
}

class GuideDog extends Dog implements Trainable {
    GuideDog(String name) {
        super(name);
    }

    public void learn(String command) {
        System.out.println(name + " learned: " + command);
    }

    void guide() {
        System.out.println(name + " is guiding safely.");
    }
}
```

Expected output:

```text
Eating.
Bruno barks.
Bruno wags its tail.
Bruno learned: Stop at the kerb
Bruno is guiding safely.
```

`GuideDog` sits at the bottom of a chain (`Animal` → `Dog` → `GuideDog`). It also gets `Pet` through `Dog`, and adds `Trainable` itself.

| Type | Shape | Allowed with classes? |
|---|---|---|
| Single | A → B | Yes |
| Multilevel | A → B → C | Yes |
| Hierarchical | A → B, A → C | Yes |
| Multiple | A, B → C | Only through interfaces |
| Hybrid | A mix of the above | Only when the "multiple" part uses interfaces |

Every Java class has a parent, even when you write no `extends`. Java quietly makes it extend **`Object`**, the root of all classes. That is why every object has methods like `toString()` and `equals()`.

## extends Keyword

`extends` creates the parent-child link.

```text
class Child extends Parent {
    // new fields and methods
}
```

Rules:

- A class can extend **only one** class.
- A class cannot extend a `final` class.
- A class can extend a class **and** implement interfaces: `class A extends B implements C, D`.
- An interface can extend other interfaces, even several: `interface C extends A, B`.

## super Keyword

`super` refers to the **parent class** part of the current object. It has two main uses.

### Calling a Parent Method

When a child replaces a parent method, it can still call the parent's version with `super.methodName()`.

This lets the child **add to** the parent's behaviour instead of rewriting it.

### Calling a Parent Constructor

`super(...)` calls the parent's constructor. It must be the **first line** of the child's constructor.

```java runnable title="super reaches the parent's method and constructor"
public class Main {
    public static void main(String[] args) {
        SavingsAccount s = new SavingsAccount("Asha", 10000, 4);
        s.showDetails();
    }
}

class BankAccount {
    String owner;
    int balance;

    BankAccount(String owner, int balance) {
        this.owner = owner;
        this.balance = balance;
    }

    void showDetails() {
        System.out.println("Owner: " + owner);
        System.out.println("Balance: " + balance);
    }
}

class SavingsAccount extends BankAccount {
    int interestRate;

    SavingsAccount(String owner, int balance, int interestRate) {
        super(owner, balance);
        this.interestRate = interestRate;
    }

    void showDetails() {
        super.showDetails();
        System.out.println("Interest rate: " + interestRate + "%");
    }
}
```

Expected output:

```text
Owner: Asha
Balance: 10000
Interest rate: 4%
```

`super(owner, balance)` lets the parent set its own fields. The child then sets only its extra field.

`super.showDetails()` prints the parent's two lines. The child then adds one more line. Nothing was copied.

| | `this` | `super` |
|---|---|---|
| Refers to | The current object | The parent part of the current object |
| `this.x` / `super.x` | This class's field | The parent's field |
| `this.m()` / `super.m()` | This class's version of `m` | The parent's version of `m` |
| `this(...)` / `super(...)` | Another constructor in this class | A constructor of the parent |

## Constructor Chaining

When you create a child object, the **parent's constructor always runs first**. Then the child's constructor runs.

This makes sense. The child is built on top of the parent, so the parent part must be ready first.

If a child constructor does not call `super(...)`, Java quietly adds `super();` as its first line. That calls the parent's **no-argument** constructor.

```java runnable title="Constructors run from the top of the family down"
public class Main {
    public static void main(String[] args) {
        new Grandchild();
    }
}

class Grandparent {
    Grandparent() {
        System.out.println("1. Grandparent constructor");
    }
}

class Parent extends Grandparent {
    Parent() {
        System.out.println("2. Parent constructor");
    }
}

class Grandchild extends Parent {
    Grandchild() {
        System.out.println("3. Grandchild constructor");
    }
}
```

Expected output:

```text
1. Grandparent constructor
2. Parent constructor
3. Grandchild constructor
```

None of these constructors writes `super()`. Java added it to each one. So the chain runs from the top class down to the bottom.

If the parent has **only** constructors with parameters, Java cannot add `super();` for you. The child must call `super(...)` with the right values, or it does not compile.

```java runnable expect-error title="The child must call the parent's constructor with values"
public class Main {
    public static void main(String[] args) {
        new Student();
    }
}

class Person {
    String name;

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

class Student extends Person {
    Student() {
        System.out.println("Student created");
    }
}
```

The compiler reports `constructor Person in class Person cannot be applied to given types`. Java tried to call `super()`, but `Person` has no constructor without parameters. The fix is to add `super("Unknown");` as the first line of `Student()`.

**Easy Way to Remember:** `this(...)` calls a constructor in the **same** class. `super(...)` calls a constructor in the **parent** class. Either one must be the first line, so a constructor can use only one of them.

## Inheritance Hierarchies

An **inheritance hierarchy** is the full family tree of related classes.

```text
                 Object
                   │
                Employee
         ┌─────────┼──────────┐
     Manager    Engineer    Intern
                   │
            SeniorEngineer
```

General ideas go near the **top**. Specific details go near the **bottom**.

- `Employee` holds what every employee has: a name, an ID and a salary.
- `Engineer` adds a programming language.
- `SeniorEngineer` adds a team to lead.

Tips for a healthy hierarchy:

- **Keep it shallow.** Three or four levels is plenty. Deep trees are hard to follow.
- **Pass the IS-A test at every level.** A senior engineer is an engineer, and an engineer is an employee.
- **Put shared code as high as it is truly shared.** Do not put a field in the parent if only one child uses it.

## Common mistakes

The following mistakes are common when using inheritance. Each row shows what you see, why it happens and how to fix it.

| Symptom | Cause | Fix |
|---|---|---|
| `'{' expected` after `extends A, B` | Two classes after `extends` | Extend one class, implement interfaces |
| `cannot be applied to given types` on a constructor | Java's automatic `super()` has no matching parent constructor | Call `super(...)` with the right values |
| `call to super must be first statement` | `super(...)` came after other code | Move it to the first line |
| `has private access` | A child used a parent's private member | Use a `protected` member or a public method |
| `cannot inherit from final` | The parent class is `final` | Use composition instead |
| Strange designs, like a car that is an engine | Inheritance used for HAS-A | Use a field instead |

## What to Remember

- Inheritance lets a child class reuse a parent's fields and methods, then add or replace behaviour.
- Use it only when the IS-A test passes. Use a field for HAS-A.
- A class `extends` one class. It can `implement` many interfaces, which gives multiple and hybrid inheritance.
- `super.method()` calls the parent's version. `super(...)` calls the parent's constructor and must come first.
- Parent constructors always run before child constructors, from the top of the hierarchy down.
- Every class ultimately extends `Object`. Keep hierarchies shallow and general at the top.

Next: Polymorphism
