LearnContact
Lesson 2250 min read

Inheritance in Java

Learn Inheritance in Java in detail, including parent and child classes, extends keyword, IS-A relationship, method inheritance, constructor chaining, super keyword, method overriding, inheritance types, access control, and best practices.

Introduction

Inheritance is one of the fundamental principles of Object-Oriented Programming. It allows a new class to reuse, extend, and specialize the behavior of an existing class.

Simple Inheritance Example
class Animal {

    void eat() {

        System.out.println(
            "Animal is eating"
        );

    }

}


class Dog extends Animal {

    void bark() {

        System.out.println(
            "Dog is barking"
        );

    }

}
Using the Child Class
Dog dog = new Dog();


dog.eat();

dog.bark();

The Dog class defines bark() itself and inherits the accessible eat() method from Animal.

What You Will Learn
  • What inheritance is.
  • Why inheritance is useful.
  • What parent and child classes are.
  • How the extends keyword works.
  • What the IS-A relationship means.
  • Which class members are inherited.
  • How access modifiers affect inheritance.
  • How constructors work with inheritance.
  • What constructor execution order is.
  • How the super keyword works.
  • How to call parent constructors.
  • How to call parent methods.
  • How constructor chaining works.
  • What method overriding is.
  • Rules of method overriding.
  • How the @Override annotation works.
  • What field hiding is.
  • What static method hiding is.
  • What single inheritance is.
  • What multilevel inheritance is.
  • What hierarchical inheritance is.
  • Why Java does not support multiple inheritance of classes.
  • How every class inherits from Object.
  • What upcasting is.
  • What downcasting is.
  • How instanceof works.
  • How final affects inheritance.
  • How abstract classes use inheritance.
  • How inheritance works with encapsulation.
  • The difference between inheritance and composition.
  • When inheritance should be used.
  • When inheritance should be avoided.

What is Inheritance?

Inheritance is the mechanism by which one class acquires accessible fields and methods from another class. The new class can reuse existing behavior and add or specialize its own behavior.

Inheritance Structure
        PARENT CLASS

           Animal

        eat()
        sleep()

            │
            │ inherited by
            ▼

         CHILD CLASS

             Dog

        eat()      inherited

        sleep()    inherited

        bark()     own method
Common Terminology
  • Parent class is also called superclass or base class.
  • Child class is also called subclass or derived class.
  • The child class extends the parent class.
  • The child class can add new members.
  • The child class can override inherited methods.

Why Use Inheritance?

Code Reuse

Common behavior can be defined once in a parent class and reused by child classes.

Specialization

Child classes can add behavior specific to their own purpose.

Method Overriding

Child classes can provide specialized implementations of inherited methods.

Class Hierarchies

Related classes can be organized into meaningful parent-child structures.

Polymorphism

Parent references can work with objects of different child classes.

Maintainability

Shared behavior can be maintained in one common location.

Real-World Analogy

Think of inheritance as specialization. A car is a vehicle. A motorcycle is also a vehicle. Both share general vehicle behavior but also have their own specialized features.

Vehicle Hierarchy
             VEHICLE

        start()
        stop()
        move()

          /       \

         /         \

        ▼           ▼

       CAR      MOTORCYCLE

   openTrunk()    kickStart()


CAR IS-A VEHICLE

MOTORCYCLE IS-A VEHICLE

Parent and Child Classes

Parent Class
class Animal {

    void eat() {

        System.out.println(
            "Eating"
        );

    }

}
Child Class
class Dog extends Animal {

    void bark() {

        System.out.println(
            "Barking"
        );

    }

}
Relationship
Animal

Parent Class
Superclass
Base Class


Dog

Child Class
Subclass
Derived Class

The extends Keyword

The extends keyword creates an inheritance relationship between two classes.

Syntax
class ChildClass
        extends ParentClass {

    // Additional fields

    // Additional methods

}
Example
class Vehicle {

}


class Car extends Vehicle {

}

Basic Inheritance Example

Animal.java
public class Animal {

    public void eat() {

        System.out.println(
            "Animal is eating"
        );

    }


    public void sleep() {

        System.out.println(
            "Animal is sleeping"
        );

    }

}
Dog.java
public class Dog
        extends Animal {

    public void bark() {

        System.out.println(
            "Dog is barking"
        );

    }

}
Main.java
public class Main {

    public static void main(
        String[] args
    ) {

        Dog dog = new Dog();


        dog.eat();

        dog.sleep();

        dog.bark();

    }

}
Output
Animal is eating

Animal is sleeping

Dog is barking

How Inheritance Works

Inheritance Flow
DOG OBJECT

        │
        ├── Own Members
        │
        │   bark()
        │
        └── Inherited Accessible Members

            eat()

            sleep()


dog.eat()

        │
        ▼

Method inherited from Animal


dog.bark()

        │
        ▼

Method declared in Dog

IS-A Relationship

Inheritance should represent an IS-A relationship. If Child extends Parent, the child should logically be a specialized type of the parent.

Valid IS-A Relationships
Dog IS-A Animal

Car IS-A Vehicle

Manager IS-A Employee

SavingsAccount IS-A BankAccount

Circle IS-A Shape
Invalid Relationship
Engine IS-A Car

Incorrect


Engine HAS-A Car?

Also incorrect


Car HAS-A Engine

Correct relationship

Use composition
Important Design Rule
  • Use inheritance for a genuine IS-A relationship.
  • Do not use inheritance only to reuse code.
  • Use composition for HAS-A relationships.
  • A Car has an Engine, so Engine should not extend Car.

Inherited Members

A child class inherits accessible members from its parent according to Java access-control rules.

Parent Class
class Parent {

    public int publicValue;

    protected int protectedValue;

    int packageValue;

    private int privateValue;


    public void publicMethod() {

    }


    protected void protectedMethod() {

    }

}
Members Available Through Inheritance
  • Public members are accessible according to normal public access.
  • Protected members support subclass access.
  • Package-private members are accessible when package rules allow it.
  • Private members are not directly accessible in the child class.
  • Constructors are not inherited.

What is Not Inherited?

Important Rules
NOT DIRECTLY INHERITED

Constructors


NOT DIRECTLY ACCESSIBLE

Private parent members


SPECIAL CASES

Static methods are hidden,
not overridden


Fields can be hidden,
not overridden

Access Modifiers in Inheritance

General Access
MODIFIER          CHILD ACCESS

public            Yes

protected         Yes

package-private   Same package

private           No direct access

Public Members

Public Member
class Parent {

    public void display() {

        System.out.println(
            "Parent method"
        );

    }

}


class Child extends Parent {

    void test() {

        display();

    }

}

Protected Members

Protected Member
class Employee {

    protected double salary;

}


class Manager extends Employee {

    void showSalary() {

        System.out.println(
            salary
        );

    }

}
Design Consideration
  • Protected members are more exposed than private members.
  • Protected mutable fields can weaken encapsulation.
  • Private fields with controlled protected methods are often safer.

Package-Private Members

A member with no explicit access modifier is package-private. A child class can access it only when normal package access rules allow it.

Same Package
class Parent {

    int value = 10;

}


class Child extends Parent {

    void display() {

        System.out.println(value);

    }

}

Private Members

Private Parent Field
class Parent {

    private int value = 10;


    public int getValue() {

        return value;

    }

}


class Child extends Parent {

    void display() {

        System.out.println(
            getValue()
        );

    }

}

The child class cannot directly access value, but it can use an accessible method provided by the parent.

Constructors and Inheritance

Constructors are not inherited. However, creating a child object requires initialization of the parent part of that object, so a parent constructor executes before the child constructor.

Constructor Example
class Parent {

    Parent() {

        System.out.println(
            "Parent constructor"
        );

    }

}


class Child extends Parent {

    Child() {

        System.out.println(
            "Child constructor"
        );

    }

}
Creating Object
Child child = new Child();
Output
Parent constructor

Child constructor

Constructor Execution Order

Execution Order
new Child()

     │
     ▼

Parent Constructor

     │
     ▼

Child Constructor

     │
     ▼

Object Ready

In a deeper hierarchy, constructors execute from the highest parent class down to the most specific child class.

The super Keyword

The super keyword refers to the parent-class part of the current object.

Common Uses of super
  • Call a parent constructor.
  • Call a parent method.
  • Access a hidden parent field.

Calling Parent Constructor

Parent Constructor
class Employee {

    private String name;


    Employee(String name) {

        this.name = name;

    }


    public String getName() {

        return name;

    }

}
Child Constructor
class Manager extends Employee {

    private String department;


    Manager(
        String name,
        String department
    ) {

        super(name);

        this.department =
                department;

    }

}
super() Rule
  • A call to super() must be the first statement in a constructor.
  • If no constructor call is written, Java attempts to insert super().
  • The parent constructor must exist and be accessible.

Calling Parent Methods

Calling Parent Implementation
class Animal {

    void sound() {

        System.out.println(
            "Animal sound"
        );

    }

}


class Dog extends Animal {

    @Override
    void sound() {

        super.sound();


        System.out.println(
            "Dog barks"
        );

    }

}

Accessing Parent Fields

Hidden Fields
class Parent {

    int value = 10;

}


class Child extends Parent {

    int value = 20;


    void display() {

        System.out.println(value);

        System.out.println(
            super.value
        );

    }

}
Output
20

10

Constructor Chaining

Multilevel Constructor Chain
class A {

    A() {

        System.out.println("A");

    }

}


class B extends A {

    B() {

        System.out.println("B");

    }

}


class C extends B {

    C() {

        System.out.println("C");

    }

}
Creating C
C object = new C();
Output
A

B

C

Default Constructor Problem

Parent Without No-Argument Constructor
class Parent {

    Parent(int value) {

    }

}


class Child extends Parent {

    Child() {

        super(10);

    }

}
Why super(10) is Required
  • The parent has no no-argument constructor.
  • Java cannot successfully insert super().
  • The child must explicitly call an available parent constructor.

Method Inheritance

Inherited Method
class Vehicle {

    void start() {

        System.out.println(
            "Vehicle started"
        );

    }

}


class Car extends Vehicle {

}


Car car = new Car();

car.start();

Method Overriding

Method overriding occurs when a child class provides its own implementation of an inherited instance method.

Method Overriding
class Animal {

    void sound() {

        System.out.println(
            "Animal makes sound"
        );

    }

}


class Dog extends Animal {

    @Override
    void sound() {

        System.out.println(
            "Dog barks"
        );

    }

}

Rules of Method Overriding

  • The child method must have the same method name.
  • The child method must have the same parameter list.
  • The return type must be compatible.
  • The child method cannot reduce access visibility.
  • Private methods are not overridden.
  • Static methods are hidden rather than overridden.
  • Final methods cannot be overridden.
  • The overriding method may use a covariant return type.
  • Checked exception rules must be respected.

@Override Annotation

Recommended Usage
@Override
public void display() {

    System.out.println(
        "Child implementation"
    );

}
Why Use @Override?
  • The compiler verifies that overriding actually occurs.
  • Typing mistakes are detected.
  • Code intent becomes clearer.
  • Maintenance becomes safer.

Calling an Overridden Parent Method

Using super.method()
class Employee {

    void work() {

        System.out.println(
            "Employee is working"
        );

    }

}


class Manager extends Employee {

    @Override
    void work() {

        super.work();


        System.out.println(
            "Manager is managing"
        );

    }

}

Field Hiding

Fields are not overridden. When a child declares a field with the same name as a parent field, the child field hides the parent field.

Field Hiding
class Parent {

    String name = "Parent";

}


class Child extends Parent {

    String name = "Child";

}

Method Overriding vs Field Hiding

Comparison
METHOD OVERRIDING

Applies to instance methods

Resolved using actual object type

Supports runtime polymorphism



FIELD HIDING

Applies to fields

Resolved using reference type

Does not provide polymorphic behavior

Static Method Hiding

Static Method Hiding
class Parent {

    static void display() {

        System.out.println("Parent");

    }

}


class Child extends Parent {

    static void display() {

        System.out.println("Child");

    }

}

Static methods belong to classes and are hidden rather than overridden.

Single Inheritance

Structure
Animal

   │
   ▼

 Dog
Single Inheritance
class Animal {

}


class Dog extends Animal {

}

Multilevel Inheritance

Structure
Animal

   │
   ▼

Mammal

   │
   ▼

 Dog
Multilevel Inheritance
class Animal {

}


class Mammal extends Animal {

}


class Dog extends Mammal {

}

Hierarchical Inheritance

Structure
          Animal

        /    |    \

       /     |     \

      ▼      ▼      ▼

     Dog    Cat    Bird
Hierarchical Inheritance
class Animal {

}


class Dog extends Animal {

}


class Cat extends Animal {

}


class Bird extends Animal {

}

Multiple Inheritance

Java does not allow a class to directly extend multiple classes.

Not Allowed
class Child
        extends ParentA, ParentB {

}


// Compilation error
Diamond Problem
       ParentA

       method()

        /    \

       /      \

      ▼        ▼

 ParentB      ParentC

 method()     method()

       \      /

        \    /

          ▼

         Child


Which implementation
should Child inherit?
Java Alternative
  • A class can extend only one class.
  • A class can implement multiple interfaces.
  • Interfaces provide controlled multiple-type inheritance.

Hybrid Inheritance

Hybrid inheritance combines multiple inheritance patterns. Java does not support every hybrid form through classes alone, but combinations can be created using classes and interfaces.

The Object Class

Every Java class directly or indirectly extends java.lang.Object.

Implicit Inheritance
class Student {

}
Conceptually Similar To
class Student extends Object {

}
Important Object Methods
  • toString()
  • equals()
  • hashCode()
  • getClass()

Upcasting

Upcasting stores a child object in a parent-type reference. It is automatic and safe.

Upcasting
Dog dog = new Dog();


Animal animal = dog;
Direct Upcasting
Animal animal =
        new Dog();

Downcasting

Downcasting converts a parent reference back to a more specific child reference. It requires an explicit cast and can fail at runtime if the object is not actually of that child type.

Valid Downcasting
Animal animal =
        new Dog();


Dog dog =
        (Dog) animal;
Invalid Downcasting
Animal animal =
        new Animal();


Dog dog =
        (Dog) animal;


// ClassCastException

instanceof Operator

Safe Type Check
if (animal instanceof Dog) {

    Dog dog =
            (Dog) animal;


    dog.bark();

}

Pattern Matching with instanceof

Pattern Matching
if (animal instanceof Dog dog) {

    dog.bark();

}

Pattern matching combines the type check and variable creation into one operation.

final Classes

Final Class
final class SecurityManager {

}


// Not allowed

class CustomManager
        extends SecurityManager {

}

A final class cannot be extended.

final Methods

Final Method
class Parent {

    final void display() {

        System.out.println(
            "Fixed behavior"
        );

    }

}

A final method can be inherited but cannot be overridden.

Abstract Classes and Inheritance

Abstract Parent
abstract class Shape {

    abstract double area();


    void display() {

        System.out.println(
            "This is a shape"
        );

    }

}
Concrete Child
class Circle extends Shape {

    private double radius;


    Circle(double radius) {

        this.radius = radius;

    }


    @Override
    double area() {

        return Math.PI
                * radius
                * radius;

    }

}

Inheritance and Encapsulation

Protected Through Methods
class Employee {

    private double salary;


    public double getSalary() {

        return salary;

    }


    protected void increaseSalary(
        double amount
    ) {

        if (amount > 0) {

            salary += amount;

        }

    }

}


class Manager extends Employee {

    void applyBonus() {

        increaseSalary(5000);

    }

}

The child class extends behavior without directly accessing the private salary field.

Inheritance vs Composition

Comparison
INHERITANCE

IS-A relationship

Car IS-A Vehicle


class Car extends Vehicle



COMPOSITION

HAS-A relationship

Car HAS-A Engine


class Car {

    private Engine engine;

}
Prefer the Correct Relationship
  • Use inheritance for genuine specialization.
  • Use composition when one object contains or uses another.
  • Do not force inheritance only to reuse implementation.
  • Composition often provides greater flexibility.

When to Use Inheritance

  • When a genuine IS-A relationship exists.
  • When the child is a true specialization of the parent.
  • When inherited behavior is logically valid for every child.
  • When polymorphism is required.
  • When the parent class provides a stable abstraction.
  • When child objects can safely be used wherever parent objects are expected.

When to Avoid Inheritance

  • When the relationship is HAS-A rather than IS-A.
  • When inheritance is used only to reuse code.
  • When the child must disable important parent behavior.
  • When the parent implementation changes frequently.
  • When deep inheritance hierarchies become difficult to understand.
  • When composition provides a simpler and more flexible design.

Vehicle Example

Vehicle.java
public class Vehicle {

    private final String brand;

    private int speed;


    public Vehicle(String brand) {

        this.brand = brand;

    }


    public String getBrand() {

        return brand;

    }


    public int getSpeed() {

        return speed;

    }


    protected void setSpeed(int speed) {

        if (speed >= 0) {

            this.speed = speed;

        }

    }


    public void start() {

        System.out.println(
            brand + " started"
        );

    }


    public void stop() {

        speed = 0;


        System.out.println(
            brand + " stopped"
        );

    }

}
Car.java
public class Car extends Vehicle {

    private final int doors;


    public Car(
        String brand,
        int doors
    ) {

        super(brand);

        this.doors = doors;

    }


    public int getDoors() {

        return doors;

    }


    public void accelerate() {

        setSpeed(
            getSpeed() + 10
        );

    }

}

Employee Example

Employee.java
public class Employee {

    private final int id;

    private String name;

    private double salary;


    public Employee(
        int id,
        String name,
        double salary
    ) {

        this.id = id;

        this.name = name;

        this.salary = salary;

    }


    public int getId() {

        return id;

    }


    public String getName() {

        return name;

    }


    public double getSalary() {

        return salary;

    }


    public void work() {

        System.out.println(
            name + " is working"
        );

    }

}
Manager.java
public class Manager
        extends Employee {

    private String department;


    public Manager(
        int id,
        String name,
        double salary,
        String department
    ) {

        super(
            id,
            name,
            salary
        );


        this.department =
                department;

    }


    @Override
    public void work() {

        System.out.println(
            getName()
            + " is managing "
            + department
        );

    }

}

Bank Account Example

BankAccount.java
public class BankAccount {

    private double balance;


    public void deposit(double amount) {

        if (amount > 0) {

            balance += amount;

        }

    }


    public boolean withdraw(
        double amount
    ) {

        if (amount <= 0 ||
            amount > balance) {

            return false;

        }


        balance -= amount;

        return true;

    }


    public double getBalance() {

        return balance;

    }

}
SavingsAccount.java
public class SavingsAccount
        extends BankAccount {

    private double interestRate;


    public SavingsAccount(
        double interestRate
    ) {

        this.interestRate =
                interestRate;

    }


    public void addInterest() {

        double interest =
                getBalance()
                * interestRate
                / 100;


        deposit(interest);

    }

}

Shape Example

Shape.java
public abstract class Shape {

    public abstract double area();


    public void displayArea() {

        System.out.println(
            "Area: " + area()
        );

    }

}
Rectangle.java
public class Rectangle
        extends Shape {

    private double width;

    private double height;


    public Rectangle(
        double width,
        double height
    ) {

        this.width = width;

        this.height = height;

    }


    @Override
    public double area() {

        return width * height;

    }

}

Common Inheritance Errors

Common Errors
INHERITANCE ERRORS

├── Using Inheritance Without IS-A Relationship
├── Using Inheritance Only for Code Reuse
├── Confusing IS-A and HAS-A
├── Trying to Extend Multiple Classes
├── Forgetting extends Keyword
├── Trying to Access Private Parent Fields Directly
├── Assuming Constructors are Inherited
├── Forgetting Parent Constructor Execution
├── Forgetting super() Rules
├── Calling super() After Another Statement
├── Missing Required Parent Constructor Call
├── Assuming Child Constructor Runs First
├── Confusing this() and super()
├── Trying to Use Both this() and super() Explicitly First
├── Incorrect Method Signature While Overriding
├── Forgetting @Override
├── Reducing Method Visibility
├── Trying to Override final Methods
├── Trying to Override Private Methods
├── Treating Static Method Hiding as Overriding
├── Treating Field Hiding as Overriding
├── Confusing Reference Type and Object Type
├── Unsafe Downcasting
├── Ignoring ClassCastException
├── Unnecessary instanceof Checks
├── Creating Deep Inheritance Hierarchies
├── Exposing Protected Mutable Fields
├── Breaking Parent Class Invariants
├── Overriding Methods Incorrectly
├── Calling Overridable Methods from Constructors
├── Creating Fragile Parent-Child Coupling
├── Violating the IS-A Relationship
├── Child Class Disabling Parent Behavior
├── Child Class Throwing UnsupportedOperationException for Parent Operations
├── Using Inheritance Instead of Composition
├── Creating God Parent Classes
├── Putting Unrelated Behavior in Base Classes
├── Duplicating Parent Logic in Child Classes
├── Forgetting super.method()
├── Overusing super
├── Depending on Parent Implementation Details
├── Breaking Encapsulation Through protected Fields
├── Assuming final Field Prevents Inheritance
├── Assuming final Class Methods Cannot Be Used
├── Forgetting Every Class Extends Object
├── Incorrect equals() in Inheritance Hierarchies
├── Incorrect hashCode() with Inheritance
├── Poor toString() Overrides
├── Overcomplicated Type Hierarchies
├── Excessive Downcasting
├── Using Type Checks Instead of Polymorphism
├── Creating Circular Design Dependencies
├── Confusing Inheritance with Object Containment
└── Ignoring Composition as an Alternative

Best Practices

  • Use inheritance only for genuine IS-A relationships.
  • Ensure the child is a true specialization of the parent.
  • Do not use inheritance only to avoid code duplication.
  • Prefer composition for HAS-A relationships.
  • Keep inheritance hierarchies shallow.
  • Design parent classes carefully.
  • Keep parent class responsibilities focused.
  • Protect parent state with encapsulation.
  • Prefer private fields over protected mutable fields.
  • Provide controlled protected methods when subclasses need extension points.
  • Use @Override whenever overriding methods.
  • Keep overriding behavior compatible with parent expectations.
  • Do not reduce method visibility.
  • Use super() explicitly when parent constructor arguments are required.
  • Understand constructor execution order.
  • Do not call overridable methods from constructors unless the design is carefully controlled.
  • Use super.method() only when parent behavior should remain part of the child behavior.
  • Avoid unnecessary field hiding.
  • Avoid static method hiding when it creates confusion.
  • Use upcasting to support polymorphism.
  • Avoid unnecessary downcasting.
  • Check types before unsafe casts.
  • Use pattern matching with instanceof when appropriate.
  • Use final classes when extension should not be allowed.
  • Use final methods when specific behavior must remain unchanged.
  • Use abstract classes for shared state and partial implementation.
  • Keep public APIs stable.
  • Avoid exposing parent implementation details.
  • Do not let child classes break parent invariants.
  • Use meaningful class hierarchies.
  • Prefer behavior-based abstractions.
  • Avoid deep chains such as A extends B extends C extends D extends E.
  • Favor simple designs.
  • Use interfaces when multiple capabilities are required.
  • Remember that Java classes support only single inheritance.
  • Remember that every class ultimately inherits from Object.
  • Override equals(), hashCode(), and toString() carefully.
  • Use polymorphism instead of repeated type checking where possible.
  • Review whether every child can safely substitute for its parent.
  • Use composition when behavior needs to change dynamically.
  • Keep inheritance relationships stable.
  • Document intended extension points.
  • Avoid fragile dependencies on parent internals.
  • Test overridden behavior.
  • Test constructor chains.
  • Design for maintainability rather than maximum reuse.
  • Use inheritance as a modeling tool, not merely a shortcut.

Common Misconceptions

Avoid These Misconceptions
  • Inheritance is not only for code reuse.
  • A child class does not inherit constructors.
  • A child class cannot directly access private parent fields.
  • Private methods are not overridden.
  • Static methods are not overridden.
  • Fields are not overridden.
  • A class cannot extend multiple classes.
  • A child constructor does not execute before the parent constructor.
  • super() is not optional when the required parent constructor needs arguments.
  • super() must be the first constructor statement.
  • this() and super() cannot both be explicit first constructor calls.
  • Method overriding is different from method overloading.
  • Upcasting does not create a new object.
  • Downcasting does not change the actual object.
  • A parent reference can refer to a child object.
  • Reference type and object type are different concepts.
  • final classes cannot be extended.
  • final methods can be inherited but not overridden.
  • Every Java class ultimately extends Object.
  • Inheritance does not automatically provide good design.
  • Deep inheritance hierarchies are not always better.
  • Composition is often more flexible than inheritance.
  • HAS-A relationships should not normally use inheritance.
  • The extends keyword represents a type relationship.
  • Protected fields are not always better than private fields.
  • A child class should preserve valid parent behavior.
  • Inheritance and polymorphism are related but different concepts.
  • Interfaces and class inheritance are not the same.
  • Multiple interface implementation is not multiple class inheritance.
  • Good inheritance requires semantic compatibility.

Practice Exercises

Exercise 1: Animal Hierarchy
  • Create an Animal parent class.
  • Add eat() and sleep() methods.
  • Create Dog and Cat child classes.
  • Add specialized methods.
  • Test inherited behavior.
Exercise 2: Vehicle Hierarchy
  • Create a Vehicle parent class.
  • Create Car and Motorcycle child classes.
  • Use constructor chaining.
  • Add specialized child behavior.
  • Override a common method.
Exercise 3: Employee Hierarchy
  • Create an Employee parent class.
  • Create Manager and Developer child classes.
  • Keep salary private.
  • Use protected behavior instead of protected fields.
  • Override work().
Exercise 4: Multilevel Inheritance
  • Create Animal.
  • Create Mammal extending Animal.
  • Create Dog extending Mammal.
  • Add one method at each level.
  • Call all accessible methods using a Dog object.
Exercise 5: Constructor Chaining
  • Create three inheritance levels.
  • Add constructors to every class.
  • Print a message from every constructor.
  • Create the lowest-level object.
  • Observe execution order.
Exercise 6: Method Overriding
  • Create a Shape parent class.
  • Create Circle and Rectangle child classes.
  • Override area().
  • Use @Override.
  • Call methods through parent references.
Exercise 7: Upcasting and Downcasting
  • Create Animal and Dog classes.
  • Store Dog in an Animal reference.
  • Call an overridden method.
  • Check with instanceof.
  • Safely downcast to Dog.
Exercise 8: Inheritance vs Composition
  • Create Car and Engine classes.
  • Use composition between Car and Engine.
  • Explain why Engine should not extend Car.
  • Create a valid inheritance relationship.
  • Compare both designs.

Common Interview Questions

What is inheritance in Java?

Inheritance is the mechanism by which one class acquires accessible fields and methods from another class and can add or specialize behavior.

Which keyword is used for class inheritance?

The extends keyword is used.

What is a superclass?

A superclass is the parent class whose accessible members can be inherited by a child class.

What is a subclass?

A subclass is a child class that extends another class.

What is an IS-A relationship?

It is a relationship where a child class is logically a specialized type of its parent class.

Are constructors inherited?

No. Constructors are not inherited.

What is the super keyword?

The super keyword refers to the parent-class part of the current object.

Can Java classes support multiple inheritance?

No. A Java class can directly extend only one class.

What is method overriding?

Method overriding occurs when a child class provides its own implementation of an inherited instance method.

Can private methods be overridden?

No. Private methods are not visible to child classes and are not overridden.

Can static methods be overridden?

No. Static methods are hidden rather than overridden.

Can final methods be overridden?

No.

What is upcasting?

Upcasting stores a child object in a parent-type reference.

What is downcasting?

Downcasting converts a parent reference to a more specific child reference using an explicit cast.

What is the root class of Java?

java.lang.Object.

What is the difference between inheritance and composition?

Inheritance represents an IS-A relationship, while composition represents a HAS-A relationship.

Frequently Asked Questions

Can a child class have its own fields and methods?

Yes. A child class can add its own fields, constructors, and methods.

Can a child class override every parent method?

No. Private, static, and final methods do not participate in normal instance-method overriding.

Can a child access private parent fields?

Not directly. It must use accessible methods provided by the parent.

Does super create a parent object?

No. super refers to the parent-class part of the current object.

Can a class use both extends and implements?

Yes. A class can extend one class and implement one or more interfaces.

Should inheritance always be preferred for code reuse?

No. Composition is often more flexible and should be considered when the relationship is not a genuine IS-A relationship.

What should I learn after Inheritance?

The next lesson covers Polymorphism in Java.

Key Takeaways

  • Inheritance is a fundamental Object-Oriented Programming principle.
  • Inheritance allows a child class to reuse accessible parent behavior.
  • The extends keyword creates class inheritance.
  • The parent class is also called superclass or base class.
  • The child class is also called subclass or derived class.
  • Inheritance should represent an IS-A relationship.
  • A Dog IS-A Animal.
  • A Car IS-A Vehicle.
  • Composition represents a HAS-A relationship.
  • A Car HAS-A Engine.
  • Public members can be inherited and accessed according to public rules.
  • Protected members support subclass access.
  • Package-private members depend on package access.
  • Private members are not directly accessible in child classes.
  • Constructors are not inherited.
  • Parent constructors execute before child constructors.
  • Constructor execution proceeds from parent to child.
  • The super keyword refers to the parent part of the current object.
  • super() calls a parent constructor.
  • super.method() calls a parent method.
  • super.field can access a hidden accessible parent field.
  • A super constructor call must be the first constructor statement.
  • Java inserts super() when possible.
  • Method overriding provides specialized child behavior.
  • Overriding requires a compatible method signature.
  • The @Override annotation should be used.
  • Private methods are not overridden.
  • Static methods are hidden.
  • Fields are hidden rather than overridden.
  • Final methods cannot be overridden.
  • Final classes cannot be extended.
  • Single inheritance uses one parent and one child.
  • Multilevel inheritance creates an inheritance chain.
  • Hierarchical inheritance gives one parent multiple children.
  • Java classes do not support multiple inheritance.
  • A class can implement multiple interfaces.
  • Every Java class ultimately extends Object.
  • Upcasting is automatic.
  • A parent reference can refer to a child object.
  • Downcasting requires an explicit cast.
  • Invalid downcasting can cause ClassCastException.
  • instanceof can check an object type.
  • Pattern matching simplifies instanceof checks.
  • Abstract classes can provide shared behavior.
  • Inheritance should preserve encapsulation.
  • Private fields are usually safer than protected mutable fields.
  • Composition is often more flexible than inheritance.
  • Deep inheritance hierarchies should be avoided.
  • Inheritance should not be used only for code reuse.
  • Good inheritance requires a genuine type relationship.
  • Child classes should remain valid substitutes for parent classes.
  • Inheritance is a foundation for runtime polymorphism.

Summary

Inheritance allows one class to extend another class and reuse accessible state and behavior. The existing class is called the parent, superclass, or base class, while the extending class is called the child, subclass, or derived class.

Java uses the extends keyword for class inheritance. A class can extend only one class directly, although it can implement multiple interfaces.

Inheritance should model a genuine IS-A relationship. A Dog is an Animal and a Car is a Vehicle. HAS-A relationships, such as a Car having an Engine, are usually better represented through composition.

Constructors are not inherited, but parent constructors execute before child constructors. The super keyword can call parent constructors, invoke parent methods, and access hidden accessible parent fields.

Method overriding allows child classes to provide specialized implementations of inherited instance methods. The @Override annotation helps the compiler verify that overriding is intentional and correct.

Java supports single, multilevel, and hierarchical class inheritance. It does not support multiple inheritance of classes, helping avoid ambiguity such as the diamond problem.

Upcasting allows a child object to be referenced through a parent type and forms the foundation of runtime polymorphism. Downcasting converts a parent reference back to a more specific child reference and must be performed carefully.

Good inheritance design preserves encapsulation, keeps hierarchies shallow, uses genuine type relationships, and considers composition whenever a HAS-A relationship or greater flexibility is required.

Lesson 22 Completed
  • You understand what inheritance is.
  • You understand why inheritance is useful.
  • You understand parent and child classes.
  • You can use the extends keyword.
  • You understand the IS-A relationship.
  • You understand inherited members.
  • You understand access modifiers in inheritance.
  • You understand constructors and inheritance.
  • You understand constructor execution order.
  • You can use the super keyword.
  • You can call parent constructors.
  • You can call parent methods.
  • You understand constructor chaining.
  • You understand method inheritance.
  • You understand method overriding.
  • You know method overriding rules.
  • You can use @Override.
  • You understand field hiding.
  • You understand static method hiding.
  • You understand single inheritance.
  • You understand multilevel inheritance.
  • You understand hierarchical inheritance.
  • You understand why Java avoids multiple class inheritance.
  • You understand the Object class.
  • You understand upcasting.
  • You understand downcasting.
  • You can use instanceof.
  • You understand pattern matching with instanceof.
  • You understand final classes.
  • You understand final methods.
  • You understand abstract classes and inheritance.
  • You understand inheritance and encapsulation.
  • You know the difference between inheritance and composition.
  • You know when to use inheritance.
  • You know when to avoid inheritance.
  • You can design inheritance hierarchies.
  • You can identify common inheritance errors.
  • You know inheritance best practices.
  • You are ready to learn Polymorphism in Java.
Next Lesson →

Polymorphism in Java