Inheritance and types of inheritance

Student, Teacher and Staff all have a name, a phone number and a way to print contact details. Copying that code three times means fixing every bug three times. Inheritance lets a class take over another class's fields and methods with one word, extends. You'll see what an inherited object looks like in memory, the types of inheritance Java allows, why it refuses multiple parents, and then practise with 10 problems.

Module 7 · OOP Pillars⏱ 24 minIntermediate10 practice problems
1 The story

Three classes, one copy-paste bug

Riya is building a small college ERP. She writes Student, then copies it to make Teacher and Staff: each has name, phone and printContact(). Then the principal asks for phone numbers to be printed with +91. She fixes it in Student, forgets Staff, and the notice board shows two formats.

Copy-paste: same code three times StudentTeacherStaff namephoneprintContactnamephoneprintContactnamephoneprintContact fix a bug? fix it three times Inheritance: write it once Person name, phone printContact() StudentTeacherStaff rollNosubjectdept extends myphatshala.in
Riya

Sir, three classes, the same three members, and I keep fixing bugs in one and forgetting the others.

Arjun Sir

Ask yourself: is a student a kind of person? Is a teacher? Then write Person once and say class Student extends Person. Student gets name, phone and printContact for free, and adds only roll number.

Riya

And the +91 fix?

Arjun Sir

One place, in Person. Every class that extends it gets the fix. That's inheritance, the second pillar.

2 Definition

What is inheritance?

Formal definition (write this in exams)

Inheritance is the mechanism by which one class (the subclass or child) acquires the fields and methods of another class (the superclass or parent), declared in Java with the extends keyword. It models an IS-A relationship, promotes code reuse, and is the basis for method overriding and runtime polymorphism. A Java class can extend exactly one class; every class that extends nothing implicitly extends java.lang.Object.

In simple words

A child class starts with everything the parent has and then adds its own extras. "A savings account is an account, plus interest."

Words you'll meet in this lesson

SuperclassThe parent (base) class being extended: Person.
SubclassThe child (derived) class: Student extends Person.
IS-AThe test for inheritance: "a Student is a Person" must make sense.
HAS-AComposition: one object holds another as a field. A car has an engine; it is not one.
Objectjava.lang.Object, the root of every class hierarchy.
Diamond problemAmbiguity when a class gets the same method from two parents.

Inheritance at a glance

Syntaxclass Student extends Person { … }
Direct parentsExactly one class. extends A, B is a compile error. A class can implement many interfaces (Lesson 7.7).
InheritedPublic and protected fields and methods; package-private ones too if both classes are in the same package
Private membersPresent inside the child object, but not accessible by name in the child's code. Reach them through inherited public methods.
ConstructorsNever inherited. The child writes its own and calls the parent's with super(...) (Lesson 7.3).
RootEvery class ends at Object, so every object has toString(), equals(), hashCode() and getClass()

Exam tip: Java supports single, multilevel and hierarchical inheritance with classes. Multiple and hybrid inheritance are supported only through interfaces. A common MCQ asks "Which inheritance is not supported by classes in Java?": the answer is multiple.

3 Types and ways to use it

The types of inheritance

Single

One child, one parent.
Savings extends Account

A ← B

Multilevel

A chain: grandchild → child → parent.
Manager extends Employee extends Person

A ← B ← C

Hierarchical

Many children share one parent.
Car, Bike, Truck extends Vehicle

A ← B, A ← C

Multilevel and hierarchical together

class Vehicle {
    String regNo;
    void start() { System.out.println(regNo + ": engine on"); }
}

class Car extends Vehicle {            // hierarchical: Car and Truck share Vehicle
    int seats;
}

class Truck extends Vehicle {
    int capacityKg;
}

class ReeferTruck extends Truck {      // multilevel: ReeferTruck → Truck → Vehicle
    int minTemp;
}

public class Main {
    public static void main(String[] args) {
        Car c = new Car();
        c.regNo = "MH-12-AB-1234";
        c.seats = 5;
        c.start();                     // inherited from Vehicle

        ReeferTruck r = new ReeferTruck();
        r.regNo = "MH-04-XY-9876";      // from Vehicle (two levels up)
        r.capacityKg = 8000;           // from Truck
        r.minTemp = -18;               // its own
        r.start();
        System.out.println(r.capacityKg + " kg at " + r.minTemp + " C");
    }
}
MH-12-AB-1234: engine on MH-04-XY-9876: engine on 8000 kg at -18 C
TypeShapeWith classes?With interfaces?
SingleA ← BYesYes
MultilevelA ← B ← CYesYes
HierarchicalA ← B, A ← CYesYes
MultipleA ← C → BNo (compile error)Yes: class C implements A, B
HybridA mix including multipleNoYes, through interfaces

The diamond problem: if class C extends A, B were allowed and both A and B had hello(), which one should c.hello() run? And if A and B both extend a class with a field, does C get one copy or two? Java avoids this by allowing only one parent class. Interfaces can be combined because they carry no instance fields, and if two interfaces bring the same default method, Java forces the class to choose (Lesson 7.7). Writing class C extends A, B gives error: '{' expected.

4 Step by step

Building a small hierarchy

  1. Find what is common, and test IS-A

    Employee and Manager both have a name and a salary. Is a manager an employee? Yes. Is a car an engine? No, a car has an engine: use a field, not inheritance.

    Inheritance is a permanent, compile-time link. Use it only when the child truly is a special kind of the parent and can be used wherever the parent is expected.
  2. Write the parent once

    class Person {
        private String name;
        Person(String name) { this.name = name; }
        String getName() { return name; }
        void greet() { System.out.println("Hi, I am " + name); }
    }
    The parent keeps its fields private (Lesson 7.1). Children will reach name only through getName() and greet().
  3. Extend it and add only what's new

    class Employee extends Person {
        private double salary;
        Employee(String name, double salary) {
            super(name);          // hand the name to Person's constructor
            this.salary = salary;
        }
    }
    Constructors are not inherited, so Employee writes its own and first calls Person's with super(name). Lesson 7.3 covers this in detail.
  4. One object holds every level's fields

    Employee e = new Employee("Asha", 50000);
    e.greet();   // Hi, I am Asha
    There is one object on the heap, not a Person object plus an Employee object. It has room for name (declared in Person) and salary (declared in Employee). When e.greet() is called, the JVM looks for greet in Employee, doesn't find it, and uses Person's.
  5. Everything ends at Object

    System.out.println(e instanceof Object);   // true
    System.out.println(e.getClass().getSuperclass());   // class Person
    Person extends nothing, so javac makes it extend Object. That's why every object, even one from your own class, has toString(), equals() and getClass() (Lesson 10.3).
5 See it happen

One object, many levels: both views

Left: the line being run and its result. Right: the class chain (left column) and the single object on the heap with a section for each level.

Person → Employee → Manager 6 steps
What you see Person p = new Person("Ravi"); Employee e = new Employee("Asha", 50000); Manager m = new Manager("Kiran", 90000, 5); System.out.println(m.name); class Boss extends Employee, Person m instanceof Person / Object p.greet() → Hi, I am Ravi e.greet() → Hi, I am Asha e.getName()→ Asha m.greet() → Hi, I am Kiran m.getSalary() → 90000.0 m.getTeamSize() → 5 true / true Manager → Employee → Person → Object error: name has private access in Person error: '{' expected (only one class after extends) A plain Person with its own method. Employee never wrote greet(), yet has it. Three levels of methods on one object. Private stays private, even for children. Two parent classes? Not in Java. Every chain ends at Object. myphatshala.in
Behind the screen Classes Heap: one object Object Person Employee Manager greet()? not in Employee → use Person's #1 Person #2 Employee #3 Manager name "Ravi""Asha""Kiran" Person salary 50000.090000.0 Employee teamSize5 Manager in the object, but only Person's code can use it Employeegreet() Persongreet() Boss ? which greet()? which copy of name? One object, one section: Person's fields. Still ONE object: a section per level. Two parents would make calls ambiguous. Object adds no fields, only methods. myphatshala.in
6 Real-world use

Inheritance in real systems

Inheritance is common in libraries and frameworks. In business code, teams use it carefully and prefer composition when the IS-A test is doubtful.

Watch it with an example: finding a method up the hierarchy

SavingsAccount extends Account. When you call a method on a savings account, the JVM looks in SavingsAccount first, then moves up to Account, then Object.

Method lookup: child first, then parent 6 steps
Animated example Object toString(), equals() … Account deposit(), getBalance() SavingsAccount addInterest() extends extends sa.addInterest() sa.addInterest() sa.deposit(500) sa.deposit(500) sa.toString() sa.toString() Where is addInterest()? found in SavingsAccount ✓ not in SavingsAccount… …found in Account ✓ not here, not in Account… …found in Object ✓ #1 SavingsAccount balance (from Account) rate (its own) one object, all fields myphatshala.in
ThrowableExceptionIOException

1. Java's own exception hierarchy

IOException extends Exception, which extends Throwable. Because of this chain, one catch (Exception e) can handle many specific errors (Module 9).

FileNotFoundException→IS-A IOException→caught by its parent type
AccountSavingsCurrent

2. Account types in banking

Savings and current accounts share an account number, holder and deposit logic in a parent class; each child adds its own rules (interest, overdraft limit).

Account→SavingsAccount extends Account→adds interest
BaseEntityid, createdAt

3. Common fields for stored records

Many projects put fields every database record needs (id, created time, updated time) in one base class that all entity classes extend.

BaseEntity→Customer, Order extend it→same audit fields

4. Framework base classes

UI and testing frameworks often give you a base class to extend. Your class inherits the framework's lifecycle code and fills in only the parts specific to your screen or test.

Framework base class→class MyScreen extends …→reuse lifecycle

Examples are simplified. Deep hierarchies (five or more levels) become hard to change; many teams follow "favour composition over inheritance" and keep chains short.

7 Run the code

Three levels, one object

class Person {
    private String name;
    Person(String name) { this.name = name; }
    String getName() { return name; }
    void greet() { System.out.println("Hi, I am " + name); }
}

class Employee extends Person {
    private double salary;
    Employee(String name, double salary) {
        super(name);
        this.salary = salary;
    }
    double getSalary() { return salary; }
}

class Manager extends Employee {
    private int teamSize;
    Manager(String name, double salary, int teamSize) {
        super(name, salary);
        this.teamSize = teamSize;
    }
    int getTeamSize() { return teamSize; }
}

public class Main {
    public static void main(String[] args) {
        Manager m = new Manager("Kiran", 90000, 5);
        m.greet();                                         // from Person
        System.out.println("Salary: " + m.getSalary());     // from Employee
        System.out.println("Team: " + m.getTeamSize());     // its own
        System.out.println(m instanceof Employee);
        System.out.println(m instanceof Person);
        System.out.println(m.getClass().getSuperclass().getSuperclass().getSimpleName());
    }
}
Hi, I am Kiran Salary: 90000.0 Team: 5 true true Person
  • class Manager extends EmployeeManager inherits from Employee, which inherits from Person: multilevel.
  • super(name, salary);Constructors aren't inherited; this line runs Employee's constructor first (Lesson 7.3).
  • m.greet()Found in Person after the JVM searches Manager and Employee.
  • instanceofTrue for the object's own class and every class above it.
8 Line by line

A Bike that uses Vehicle's method

Watch one object (#1) hold a field declared in Vehicle and a field declared in Bike, and see describe() run from the parent class.

Worked examples: real problems, solved and traced in memory

Three hierarchies from real businesses. Run each solution, then step through it: notice that new creates one object whose fields come from every class in the chain, and that an inherited method runs with this pointing at the child object.

Example 1Banking · savings account

Interest on an inherited balance

Problem statement

A bank's Account class already handles deposits and keeps the balance private. Add a SavingsAccount that can credit monthly interest, without copying any of Account's code.

Input
deposit Rs 12000, monthly rate 0.5%
Expected output
Balance: 12060.0

Approach

  1. Write SavingsAccount extends Account and add only a rate field and creditInterest().
  2. The child can't touch the private balance, so it uses the inherited getBalance() and deposit().
  3. Create one SavingsAccount and call both inherited and own methods on it.

Solution: run it live

What happens in memory, step by step

Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.

Example 2Logistics · cold chain

A three-level truck, built in one go

Problem statement

A cold-chain company tracks refrigerated trucks. Every vehicle has a registration number; every truck has a capacity; a refrigerated truck also has a minimum temperature. Create one refrigerated truck and print a dispatch line.

Input
ReeferTruck "MH-04-XY-9876", 8000 kg, -18 C
Expected output
MH-04-XY-9876 | 8000 kg | -18 C

Approach

  1. Build a chain: Vehicle → Truck → ReeferTruck, each with its own field and constructor.
  2. Each constructor first calls its parent's constructor with super(...), passing the values up.
  3. Watch three constructor frames stack up, then unwind, while one object (#1) fills in.

Solution: run it live

What happens in memory, step by step

Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.

Example 3HR · ID badges

One parent method, two different children

Problem statement

An office prints ID badges. Developers and testers are both employees with a name; each adds one detail of their own. The badge-printing code must be written only once.

Input
Developer "Neha" (team Payments), Tester "Imran" (team Search)
Expected output
Neha [Payments] Java
Imran [Search] Selenium

Approach

  1. Put name, team and badge() in the parent Employee.
  2. Developer and Tester extend it: hierarchical inheritance.
  3. Call the same inherited badge() on both objects and watch this change.

Solution: run it live

What happens in memory, step by step

Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.

9 Quiz and revision

Check yourself

Quick revision

Lesson 7.2 in one screen

  • Inheritance: a subclass gets the superclass's members with extends; it models IS-A.
  • Types with classes: single, multilevel, hierarchical. Multiple and hybrid: only via interfaces.
  • One parent class only: extends A, B doesn't compile (diamond problem).
  • Private members exist in the child object but aren't accessible by name; use the parent's methods.
  • Constructors are not inherited; the child calls the parent's with super(...).
  • new Child() creates one object holding every level's fields.
  • Every class ultimately extends Object.

Interview and viva questions

Why doesn't Java support multiple inheritance of classes?

To avoid the diamond problem and keep the language simple. If a class had two parents with the same method, a call would be ambiguous; if both inherited fields from a common ancestor, the object's layout would be unclear. Java allows multiple inheritance of type through interfaces, which have no instance fields, and resolves clashing default methods by forcing the class to override.

Is a private member inherited?

The private field is present in the child object (memory is set aside for it), but it is not inherited as an accessible member: the child's code can't name it. The child uses it indirectly through the parent's public or protected methods. Interviewers accept either wording if you explain this difference.

What is the difference between IS-A and HAS-A?

IS-A is inheritance: a SavingsAccount is an Account. HAS-A is composition: a Car has an Engine field. Composition is more flexible because the part can be replaced at run time and the classes stay loosely coupled.

Why are constructors not inherited?

A constructor's job is to initialise an object of its own class. A parent's constructor knows nothing about the child's extra fields, so letting new Child(...) use it would leave the child part uninitialised. Instead every child constructor calls a parent constructor first (explicitly or implicitly) and then sets up its own part.

When should you avoid inheritance?

When the IS-A test fails, when you only want to reuse a few methods, or when the parent may change often. Prefer composition then. A well-known example is Java's own java.util.Stack, which extends Vector: every stack also inherits methods like add(int index, E element) that break the last-in, first-out rule.

Practice problems

For each problem, first draw the class hierarchy on paper (parent at the top, arrows pointing up), then decide which class each field and method belongs in. The last three are business problems.

P1Easy

Dog inherits from Animal

Create Animal with a name field and an eat() method. Create Dog extends Animal with its own bark(). Call both methods on a Dog.

Input
Dog named "Sheru"
Expected output
Sheru is eating
Sheru says Woof
Show solution and explanation
class Animal {
    String name;

    void eat() {
        System.out.println(name + " is eating");
    }
}

class Dog extends Animal {
    void bark() {
        System.out.println(name + " says Woof");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog d = new Dog();
        d.name = "Sheru";
        d.eat();
        d.bark();
    }
}
Sheru is eating Sheru says Woof

How it works: Dog declares only bark(), yet d.eat() and d.name work because they are inherited from Animal. Inside bark(), the inherited field name is used just like Dog's own.

P2Easy

Which class is the parent?

Use getClass().getSuperclass() to print the parent of Student, then the parent of Person, for the hierarchy Student extends Person.

Input
class Person {}  class Student extends Person {}
Expected output
Class: Student
Parent: Person
Grandparent: Object
Show solution and explanation
class Person { }

class Student extends Person { }

public class Main {
    public static void main(String[] args) {
        Student s = new Student();
        System.out.println("Class: " + s.getClass().getSimpleName());
        System.out.println("Parent: " + s.getClass().getSuperclass().getSimpleName());
        System.out.println("Grandparent: " + s.getClass().getSuperclass().getSuperclass().getSimpleName());
    }
}
Class: Student Parent: Person Grandparent: Object

How it works: Person has no extends, so javac makes it extend Object. That's why the grandparent of Student is Object. getClass() itself is a method every object inherits from Object.

P3Easy

Rectangle and Square (multilevel)

Make Shape with a colour, Rectangle extends Shape with length and width and an area() method, and Square extends Rectangle with a method setSide(int) that sets both sides. Print a red square's area.

Input
Square, colour red, side 6
Expected output
A red square of area 36
Show solution and explanation
class Shape {
    String colour;
}

class Rectangle extends Shape {
    int length, width;

    int area() {
        return length * width;
    }
}

class Square extends Rectangle {
    void setSide(int side) {
        length = side;
        width = side;
    }
}

public class Main {
    public static void main(String[] args) {
        Square sq = new Square();
        sq.colour = "red";
        sq.setSide(6);
        System.out.println("A " + sq.colour + " square of area " + sq.area());
    }
}
A red square of area 36

How it works: a three-level chain. colour comes from Shape (two levels up), length, width and area() from Rectangle, setSide is Square's own. One Square object holds all three fields.

P4Easy

instanceof up the chain

For Laptop extends Computer extends Device, check whether a Laptop object is an instance of each class and of Object. Also check whether a plain Device is a Laptop.

Input
new Laptop(), new Device()
Expected output
laptop is Computer: true
laptop is Device: true
laptop is Object: true
device is Laptop: false
Show solution and explanation
class Device { }
class Computer extends Device { }
class Laptop extends Computer { }

public class Main {
    public static void main(String[] args) {
        Laptop l = new Laptop();
        Device d = new Device();
        System.out.println("laptop is Computer: " + (l instanceof Computer));
        System.out.println("laptop is Device: " + (l instanceof Device));
        System.out.println("laptop is Object: " + (l instanceof Object));
        System.out.println("device is Laptop: " + (d instanceof Laptop));
    }
}
laptop is Computer: true laptop is Device: true laptop is Object: true device is Laptop: false

How it works: IS-A works only upward. Every Laptop is a Computer, a Device and an Object. A plain Device is not a Laptop, because a Device object doesn't have the Laptop part.

P5Medium

Hierarchical: three kinds of employees

Employee has a name and a describe() method. Developer, Tester and Designer each extend Employee and add one field of their own (language, tool, software). Create one of each and print their details.

Input
Dev "Neha" (Java), Tester "Imran" (Selenium), Designer "Pooja" (Figma)
Expected output
Neha - codes in Java
Imran - tests with Selenium
Pooja - designs in Figma
Show solution and explanation
class Employee {
    String name;

    void describe() {
        System.out.print(name + " - ");
    }
}

class Developer extends Employee {
    String language;
}

class Tester extends Employee {
    String tool;
}

class Designer extends Employee {
    String software;
}

public class Main {
    public static void main(String[] args) {
        Developer d = new Developer();
        d.name = "Neha";
        d.language = "Java";
        Tester t = new Tester();
        t.name = "Imran";
        t.tool = "Selenium";
        Designer g = new Designer();
        g.name = "Pooja";
        g.software = "Figma";

        d.describe(); System.out.println("codes in " + d.language);
        t.describe(); System.out.println("tests with " + t.tool);
        g.describe(); System.out.println("designs in " + g.software);
    }
}
Neha - codes in Java Imran - tests with Selenium Pooja - designs in Figma

How it works: three children share one parent: hierarchical inheritance. The common part (name, describe) is written once. Each child adds only its special field. A Tester has no language field: siblings don't share each other's members.

P6Medium

Private field, public door

Account has a private balance and a public deposit() and getBalance(). SavingsAccount extends Account adds addInterest(rate). Since the child can't touch balance directly, implement addInterest using the inherited methods.

Input
deposit 20000, interest 3.5%
Expected output
Balance after interest: 20700.0
Show solution and explanation
class Account {
    private double balance;

    public void deposit(double amount) {
        if (amount > 0) balance += amount;
    }

    public double getBalance() {
        return balance;
    }
}

class SavingsAccount extends Account {
    void addInterest(double ratePercent) {
        double interest = getBalance() * ratePercent / 100;
        deposit(interest);
    }
}

public class Main {
    public static void main(String[] args) {
        SavingsAccount s = new SavingsAccount();
        s.deposit(20000);
        s.addInterest(3.5);
        System.out.println("Balance after interest: " + s.getBalance());
    }
}
Balance after interest: 20700.0

How it works: writing balance += interest in SavingsAccount would be a compile error: balance has private access in Account. Using getBalance() and deposit() keeps the parent's rules in force for the child too: encapsulation and inheritance working together.

P7Medium

Count objects at every level

Each class in Vehicle → Car → SportsCar keeps a static counter that its constructor increases. Create 2 Vehicles, 1 Car and 2 SportsCars and print all three counters. Predict first.

Input
2 Vehicle, 1 Car, 2 SportsCar
Expected output
Vehicle constructor ran 5 times
Car constructor ran 3 times
SportsCar constructor ran 2 times
Show solution and explanation
class Vehicle {
    static int count;
    Vehicle() { count++; }
}

class Car extends Vehicle {
    static int count;
    Car() { count++; }
}

class SportsCar extends Car {
    static int count;
    SportsCar() { count++; }
}

public class Main {
    public static void main(String[] args) {
        new Vehicle(); new Vehicle();
        new Car();
        new SportsCar(); new SportsCar();
        System.out.println("Vehicle constructor ran " + Vehicle.count + " times");
        System.out.println("Car constructor ran " + Car.count + " times");
        System.out.println("SportsCar constructor ran " + SportsCar.count + " times");
    }
}
Vehicle constructor ran 5 times Car constructor ran 3 times SportsCar constructor ran 2 times

How it works: creating a SportsCar runs SportsCar's constructor, which first (silently) runs Car's, which first runs Vehicle's. So every SportsCar also counts as a Car and a Vehicle: Vehicle 2 + 1 + 2 = 5, Car 1 + 2 = 3, SportsCar 2. Lesson 7.3 explains this hidden super() call.

P8Business problem

Savings and current accounts

A bank has savings accounts (4% yearly interest) and current accounts (overdraft up to Rs 10,000). Both share account number, balance and deposit. Write the classes and show a savings account earning one year's interest and a current account going into overdraft.

Input
Savings SB-01 deposit 50000, add yearly interest
Current CA-07 deposit 5000, withdraw 12000
Expected output
SB-01: Rs 52000.0
Withdraw 12000: true
CA-07: Rs -7000.0
Show solution and explanation
class Account {
    private final String accountNo;
    protected double balance;

    Account(String accountNo) {
        this.accountNo = accountNo;
    }

    void deposit(double amount) {
        if (amount > 0) balance += amount;
    }

    String summary() {
        return accountNo + ": Rs " + balance;
    }
}

class SavingsAccount extends Account {
    SavingsAccount(String no) { super(no); }

    void addYearlyInterest() {
        balance += balance * 0.04;
    }
}

class CurrentAccount extends Account {
    private static final double OVERDRAFT = 10000;

    CurrentAccount(String no) { super(no); }

    boolean withdraw(double amount) {
        if (balance - amount < -OVERDRAFT) return false;
        balance -= amount;
        return true;
    }
}

public class Main {
    public static void main(String[] args) {
        SavingsAccount s = new SavingsAccount("SB-01");
        s.deposit(50000);
        s.addYearlyInterest();
        System.out.println(s.summary());

        CurrentAccount c = new CurrentAccount("CA-07");
        c.deposit(5000);
        System.out.println("Withdraw 12000: " + c.withdraw(12000));
        System.out.println(c.summary());
    }
}
SB-01: Rs 52000.0 Withdraw 12000: true CA-07: Rs -7000.0

How it works:

  1. Common data and deposit/summary live in Account; each child adds only its own rule.
  2. balance is protected here so children can update it directly; accountNo stays private and read-only.
  3. 5000 − 12000 = −7000, which is within the Rs 10,000 overdraft, so the withdrawal is allowed.
P9Business problem

Payroll for full-time and contract staff

Full-time staff get basic + 40% HRA; contract staff get an hourly rate × hours. Both have an employee ID and name and a method to print a payslip line. Design the hierarchy and print payslips for one of each.

Input
FullTime E101 "Anil", basic 40000
Contract C207 "Sara", Rs 600/hour × 120 hours
Expected output
E101 Anil   Rs 56,000.00
C207 Sara   Rs 72,000.00
Show solution and explanation
class Employee {
    private final String id;
    private final String name;

    Employee(String id, String name) {
        this.id = id;
        this.name = name;
    }

    void printSlip(double pay) {
        System.out.printf("%s %-6s Rs %,.2f%n", id, name, pay);
    }
}

class FullTimeEmployee extends Employee {
    private final double basic;

    FullTimeEmployee(String id, String name, double basic) {
        super(id, name);
        this.basic = basic;
    }

    double monthlyPay() {
        return basic + basic * 0.40;
    }
}

class ContractEmployee extends Employee {
    private final double hourlyRate;
    private final int hours;

    ContractEmployee(String id, String name, double hourlyRate, int hours) {
        super(id, name);
        this.hourlyRate = hourlyRate;
        this.hours = hours;
    }

    double monthlyPay() {
        return hourlyRate * hours;
    }
}

public class Main {
    public static void main(String[] args) {
        FullTimeEmployee f = new FullTimeEmployee("E101", "Anil", 40000);
        ContractEmployee c = new ContractEmployee("C207", "Sara", 600, 120);
        f.printSlip(f.monthlyPay());
        c.printSlip(c.monthlyPay());
    }
}
E101 Anil Rs 56,000.00 C207 Sara Rs 72,000.00

How it works:

  1. ID, name and payslip formatting are common, so they live in Employee. The pay rules differ, so each child has its own monthlyPay().
  2. %,.2f prints Indian-readable amounts with commas and two decimals; %-6s pads the name.
  3. Notice both children have a method with the same name. In Lesson 7.4 you'll declare it in the parent and override it, so a payroll loop can treat all employees alike.
P10Business problem

Delivery vehicles: can it carry the parcel?

A courier company has bikes (max 20 kg) and vans (max 800 kg, needs a driver with a commercial licence). All vehicles have a registration number and a canCarry(weight) check based on their limit. Check a 15 kg and a 120 kg parcel for one bike and one van.

Input
Bike MH-02-1111 (20 kg), Van MH-02-9999 (800 kg)
parcels 15 kg and 120 kg
Expected output
15 kg -> bike true, van true
120 kg -> bike false, van true
MH-02-9999 needs commercial licence: true
Show solution and explanation
class DeliveryVehicle {
    private final String regNo;
    private final int maxKg;

    DeliveryVehicle(String regNo, int maxKg) {
        this.regNo = regNo;
        this.maxKg = maxKg;
    }

    boolean canCarry(int kg) {
        return kg <= maxKg;
    }

    String getRegNo() { return regNo; }
}

class Bike extends DeliveryVehicle {
    Bike(String regNo) { super(regNo, 20); }
}

class Van extends DeliveryVehicle {
    private final boolean commercialLicence = true;

    Van(String regNo) { super(regNo, 800); }

    boolean needsCommercialLicence() { return commercialLicence; }
}

public class Main {
    public static void main(String[] args) {
        Bike b = new Bike("MH-02-1111");
        Van v = new Van("MH-02-9999");
        int[] parcels = {15, 120};
        for (int kg : parcels) {
            System.out.println(kg + " kg -> bike " + b.canCarry(kg) + ", van " + v.canCarry(kg));
        }
        System.out.println(v.getRegNo() + " needs commercial licence: " + v.needsCommercialLicence());
    }
}
15 kg -> bike true, van true 120 kg -> bike false, van true MH-02-9999 needs commercial licence: true

How it works:

  1. The rule kg <= maxKg is the same for every vehicle, so it's written once in the parent. Children only supply their limit through super(regNo, 20).
  2. Van adds a behaviour the bike doesn't have. Hierarchical inheritance: two children, one parent.
  3. Adding a new vehicle type (a three-wheeler, 300 kg) is one small class.

Real-world scenario questions (asked in company interviews)

Inheritance saves code when the IS-A test holds and causes pain when it doesn't. Decide your answer first, then open the model answer.

Banking · account typesFresher

Designing savings and current accounts

A bank needs savings accounts (interest, minimum balance) and current accounts (overdraft limit, no interest). Both have account number, holder name, balance and deposit. How would you design the classes?

The interviewer is checking: can you find the common parent and keep each child's rules separate?

Show a strong answer
  • A parent Account with private accountNo, holder, balance, plus deposit() and getBalance().
  • SavingsAccount extends Account adds rate and addInterest(); CurrentAccount extends Account adds overdraftLimit.
  • Each child has its own withdraw rule (minimum balance vs overdraft), which is where overriding comes in (Lesson 7.4).
  • Both pass the IS-A test, and code that needs "any account" can accept Account.

Avoid: one class with a type field and if-else everywhere. Every new account type would change every method.

Logistics · fleet1–3 years

"ElectricTruck extends Truck, Battery"

A delivery company adds electric trucks. A developer wants ElectricTruck to extend both Truck and Battery to reuse chargeLevel(), and is surprised it doesn't compile. What do you suggest?

The interviewer is checking: do you know the single-parent rule and when to use composition?

Show a strong answer
  • Java allows one parent class. More importantly, a truck is not a battery; it has a battery.
  • Design: ElectricTruck extends Truck with a field private final Battery battery, and a method chargeLevel() that delegates to battery.level().
  • If many vehicle types need to be "chargeable", define an interface Chargeable and implement it (Lesson 7.7).

Avoid: making Battery the parent of Truck just to get the method. The hierarchy would make no sense.

E-commerce · catalogue1–3 years

The six-level product hierarchy

A catalogue has Product → Electronics → Mobile → Smartphone → AndroidPhone → FoldablePhone. Adding a "refurbished" option now needs a parallel set of classes for every level. What went wrong and how would you restructure?

The interviewer is checking: do you recognise when inheritance is being used for data that should be attributes?

Show a strong answer
  • The hierarchy encodes data (category, OS, form factor, condition) as classes. Every new dimension multiplies the number of classes.
  • Keep a shallow hierarchy only where behaviour truly differs, and model the rest as fields: category, attributes map, condition enum (Lesson 10.4).
  • Shared behaviour like pricing rules can be separate objects composed into the product.

Avoid: adding RefurbishedFoldablePhone and friends. Deep, wide hierarchies are hard to change.

SaaS · shared library3+ years

A parent-class change broke ten teams

Your platform team owns BaseService, which 40 services across ten teams extend. You add a validation step inside one of its methods, and several child services break because they depended on the old internal order of calls. How do you prevent this in future?

The interviewer is checking: do you understand that inheritance tightly couples children to the parent's internals?

Show a strong answer
  • This is the "fragile base class" problem: children depend on how the parent works, not just what it promises.
  • Prefer composition for shared libraries: services use helper objects instead of extending a base class.
  • Where inheritance stays, document which methods are meant to be overridden, make the rest final (Lesson 7.8), and use template methods with clear hooks (Lesson 7.6).
  • Version the library and run the dependent teams' tests before releasing.

Avoid: blaming the child teams. A widely extended base class is a public contract.