Programming in Java

Unit 8: Inheritance & Polymorphism

Master class hierarchies, method overriding, dynamic dispatch, and build real-world OOP systems that mirror India's top tech products.

⏱️ 7 hrs theory + 5 hrs lab  |  💰 ₹10K–₹30K/month  |  📝 30 MCQs (Bloom's Mapped)

💼 Jobs this unlocks: Java Developer (₹5–8 LPA)  |  Android Developer (₹6–10 LPA)  |  Software Engineer (₹8–15 LPA)

Section A

Opening Hook — The Code Behind Every UPI Payment

🏢 How Paytm Handles Crores of Payments with One Class Hierarchy

Every time you pay ₹50 for chai using Paytm, a class hierarchy fires up behind the scenes. At the top sits an abstract class PaymentMethod with a method processPayment(double amount). Below it: UPIPayment, NetBankingPayment, CardPayment, and WalletPayment — each extends PaymentMethod and overrides processPayment() with its own logic.

UPI routes through NPCI. NetBanking talks to the bank's IMPS gateway. Cards hit Visa/Mastercard APIs. Wallets debit the internal ledger. One parent. Four children. Four different behaviours. One method name. That's polymorphism.

Paytm processes 1.5 billion+ transactions monthly. Without inheritance and polymorphism, they'd need separate, duplicated codebases for each payment type — unmaintainable chaos. Instead, a single line paymentMethod.processPayment(amount) handles everything through dynamic method dispatch.

Every payment hierarchy you see in Indian fintech is Java inheritance in action.

🇮🇳 Paytm🇮🇳 PhonePe🇮🇳 Google Pay🇮🇳 CRED🇮🇳 Razorpay
Java runs on 3+ billion devices worldwide — from Android phones in Tier-3 Indian cities to IRCTC's backend servers, SBI's core banking, and Aadhaar authentication. Every major Indian bank's backend is built with Java class hierarchies using inheritance and polymorphism. Learning this unit literally teaches you the architecture behind India's digital economy.
Section B

Learning Outcomes — Bloom's Taxonomy Mapped

Bloom's LevelLearning Outcome
🔵 RememberDefine inheritance, list the types of inheritance supported in Java, and recall the syntax of the extends keyword
🔵 RememberState the 5 rules of method overriding and identify the 3 uses of the super keyword
🔵 UnderstandExplain why Java doesn't support multiple inheritance with classes (diamond problem) and how interfaces solve it
🔵 UnderstandDifferentiate between compile-time polymorphism (overloading) and runtime polymorphism (overriding) with examples
🟢 ApplyImplement a Shape class hierarchy with Circle, Rectangle, and Triangle using method overriding to calculate area
🟢 ApplyBuild a BankAccount hierarchy with SavingsAccount and CurrentAccount using super to invoke parent constructors
🟢 AnalyzeTrace the output of programs involving dynamic method dispatch and predict which overridden method executes at runtime
🟢 AnalyzeCompare access modifier rules in method overriding and identify compilation errors in given code
🟠 EvaluateAssess whether a given class design violates the Liskov Substitution Principle and suggest corrections
🟠 EvaluateJustify when to use final on a class vs. method vs. variable in a real-world banking application
🟠 CreateDesign a complete Payment Gateway system using abstract classes, inheritance, and polymorphic method dispatch
🟠 CreateCreate a Swing GUI application by extending JFrame, overriding paint(), and adding custom event handlers
Section C

Concept Explanation — Inheritance & Polymorphism from Scratch

Inheritance = Family Business. Think of it like a father who owns a general store. His son inherits the shop (all the shelves, stock, billing system). But the son can customize (override) the products — maybe adding organic food the father never sold. The son doesn't build a new shop from scratch; he extends the existing one. That's Java inheritance: a child class inherits fields and methods from a parent class and can override behaviour.

1. Types of Inheritance in Java

Inheritance allows a new class to acquire the properties and behaviours of an existing class. The existing class is called the parent/super/base class, and the new class is the child/sub/derived class.

📋 Inheritance Types Supported in Java

Single Inheritance: One child extends one parent. Dog extends Animal

Multilevel Inheritance: Chain of inheritance. Puppy extends Dog extends Animal

Hierarchical Inheritance: Multiple children extend the same parent. Dog extends Animal, Cat extends Animal

❌ Multiple Inheritance (with classes): NOT supported. One class cannot extend two classes. class C extends A, B → Compilation Error!

TypeStructureJava SupportExample
SingleA → B✅ YesBankAccount → SavingsAccount
MultilevelA → B → C✅ YesAccount → SavingsAccount → SeniorCitizenAccount
HierarchicalA → B, A → C✅ YesShape → Circle, Shape → Rectangle
MultipleA,B → C❌ No (classes)Use interfaces instead
HybridMix of above❌ No (classes)Use interfaces instead
Students often ask: "Why can't Java support multiple inheritance?" Because of the Diamond Problem. If class C extends both A and B, and both A and B have a method display(), which display() does C inherit? The ambiguity is unresolvable. Java avoids this entirely by disallowing multiple inheritance with classes. Use interface instead — a class can implement multiple interfaces.
Java
// Single Inheritance
class Animal {
    void eat() {
        System.out.println("Animal eats");
    }
}

class Dog extends Animal {
    void bark() {
        System.out.println("Dog barks");
    }
}

// Multilevel Inheritance
class Puppy extends Dog {
    void play() {
        System.out.println("Puppy plays");
    }
}

// Hierarchical Inheritance
class Cat extends Animal {
    void meow() {
        System.out.println("Cat meows");
    }
}

2. The extends Keyword & IS-A Relationship

The extends keyword establishes an IS-A relationship. When you write class SavingsAccount extends BankAccount, you're saying "a SavingsAccount IS-A BankAccount." Every SavingsAccount is a BankAccount, but not every BankAccount is a SavingsAccount.

Java
class BankAccount {
    protected String accountHolder;
    protected double balance;

    public BankAccount(String holder, double balance) {
        this.accountHolder = holder;
        this.balance = balance;
    }

    public void deposit(double amount) {
        balance += amount;
        System.out.println("Deposited: ₹" + amount);
    }

    public void displayBalance() {
        System.out.println(accountHolder + " — Balance: ₹" + balance);
    }
}

class SavingsAccount extends BankAccount {
    private double interestRate;

    public SavingsAccount(String holder, double balance, double rate) {
        super(holder, balance);  // calls parent constructor
        this.interestRate = rate;
    }

    public double calculateInterest() {
        return balance * interestRate / 100;
    }
}

3. The super Keyword — 3 Uses

🔑 Three Uses of super

Use 1 — Access Parent's Variable

When child and parent have a variable with the same name, use super.variableName to access the parent's version.

Use 2 — Call Parent's Method

When child overrides a parent method but still wants to call the parent's version: super.methodName().

Use 3 — Call Parent's Constructor

super(arguments) calls the parent's constructor. Must be the first statement in child's constructor.

Java
// Use 1: Access parent variable
class Vehicle {
    int speed = 100;
}

class Car extends Vehicle {
    int speed = 200;

    void showSpeeds() {
        System.out.println("Car speed: " + speed);           // 200
        System.out.println("Vehicle speed: " + super.speed); // 100
    }
}

// Use 2: Call parent method
class Animal {
    void sound() { System.out.println("Animal makes sound"); }
}

class Dog extends Animal {
    void sound() {
        super.sound();  // calls Animal's sound()
        System.out.println("Dog barks");
    }
}

// Use 3: Call parent constructor
class Person {
    String name;
    Person(String name) { this.name = name; }
}

class Student extends Person {
    int rollNo;
    Student(String name, int rollNo) {
        super(name);   // MUST be first statement
        this.rollNo = rollNo;
    }
}
super() must be the first statement in a constructor. Putting any code before super() causes a compile error. Also, you cannot use super in a static context — it only works in instance methods and constructors.

4. Method Overriding — 5 Rules & @Override

Method overriding allows a child class to provide a specific implementation of a method already defined in the parent class. This is the foundation of runtime polymorphism.

📋 5 Rules of Method Overriding

Rule 1: Method name must be exactly the same as the parent's method

Rule 2: Parameter list must be exactly the same (same types, same order)

Rule 3: There must be an IS-A relationship (child extends parent)

Rule 4: Access modifier cannot be more restrictive. If parent is public, child can't be protected or private

Rule 5: Return type must be the same or covariant (a subclass of the original return type)

Parent AccessChild Can BeChild Cannot Be
publicpublicprotected, default, private
protectedprotected, publicdefault, private
defaultdefault, protected, publicprivate
privateCannot be overridden (not inherited)

The @Override annotation tells the compiler "I intend to override a parent method." If the method doesn't actually override anything (typo in name, wrong params), the compiler throws an error — saving you from hard-to-find bugs.

Java
class Shape {
    public double area() {
        return 0;
    }
}

class Circle extends Shape {
    double radius;

    Circle(double r) { this.radius = r; }

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

class Rectangle extends Shape {
    double length, width;

    Rectangle(double l, double w) { length = l; width = w; }

    @Override
    public double area() {
        return length * width;
    }
}

class Triangle extends Shape {
    double base, height;

    Triangle(double b, double h) { base = b; height = h; }

    @Override
    public double area() {
        return 0.5 * base * height;
    }
}

public class ShapeTest {
    public static void main(String[] args) {
        Shape[] shapes = {
            new Circle(5),
            new Rectangle(4, 6),
            new Triangle(3, 8)
        };
        for (Shape s : shapes) {
            System.out.println(s.getClass().getSimpleName()
                + " area: " + s.area());
        }
    }
}
Circle area: 78.53981633974483 Rectangle area: 24.0 Triangle area: 12.0

5. The Object Class — Mother of All Classes

Every class in Java implicitly extends java.lang.Object. Even if you write class Dog { }, it secretly becomes class Dog extends Object { }. The Object class provides methods you can override:

MethodDefault BehaviourWhy Override?
toString()Returns ClassName@hashcodeReturn a meaningful string representation
equals(Object)Compares references (==)Compare actual content/values
hashCode()Returns memory-based hashConsistency with equals for HashMap/HashSet
getClass()Returns runtime classCannot override (final method)
clone()Shallow copy of objectDeep copy support (implement Cloneable)
Java
class Student {
    String name;
    int rollNo;

    Student(String name, int rollNo) {
        this.name = name;
        this.rollNo = rollNo;
    }

    @Override
    public String toString() {
        return "Student{" + name + ", Roll: " + rollNo + "}";
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Student s = (Student) obj;
        return rollNo == s.rollNo && name.equals(s.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, rollNo);
    }
}
Always override hashCode() when you override equals(). If two objects are equal (equals() returns true), they MUST have the same hash code. Violating this contract breaks HashMap and HashSet. This is a classic interview question at TCS, Infosys, and Wipro.

6. Compile-Time vs Runtime Polymorphism

Polymorphism means "many forms." A single method name behaves differently based on context.

FeatureCompile-Time (Static)Runtime (Dynamic)
MechanismMethod OverloadingMethod Overriding
BindingEarly binding (at compile time)Late binding (at runtime)
Method SignatureSame name, different parametersSame name, same parameters
Inheritance Required?No — can be in same classYes — must be in parent-child
PerformanceSlightly faster (resolved at compile)Slightly slower (resolved at runtime)
Exampleadd(int,int) vs add(double,double)Parent ref calling child's overridden method

7. Dynamic Method Dispatch (Runtime Polymorphism)

This is the most powerful feature of inheritance. A parent reference variable can hold a child object, and when you call an overridden method, Java decides at runtime which version to execute based on the actual object type — not the reference type.

Java
class PaymentMethod {
    public void processPayment(double amount) {
        System.out.println("Processing generic payment: ₹" + amount);
    }
}

class UPIPayment extends PaymentMethod {
    @Override
    public void processPayment(double amount) {
        System.out.println("UPI Payment via NPCI: ₹" + amount);
    }
}

class CardPayment extends PaymentMethod {
    @Override
    public void processPayment(double amount) {
        System.out.println("Card Payment via Visa/MC: ₹" + amount);
    }
}

class WalletPayment extends PaymentMethod {
    @Override
    public void processPayment(double amount) {
        System.out.println("Wallet debit: ₹" + amount);
    }
}

public class PaymentGateway {
    public static void main(String[] args) {
        PaymentMethod[] methods = {
            new UPIPayment(),
            new CardPayment(),
            new WalletPayment()
        };

        for (PaymentMethod pm : methods) {
            pm.processPayment(500);  // Dynamic dispatch!
        }
    }
}
UPI Payment via NPCI: ₹500.0 Card Payment via Visa/MC: ₹500.0 Wallet debit: ₹500.0
The variable type is PaymentMethod, but the actual objects are UPIPayment, CardPayment, etc. Java looks at the actual object (not the reference type) to decide which processPayment() to call. This is dynamic method dispatch — the core of runtime polymorphism.

8. instanceof Operator & Pattern Matching (Java 16+)

The instanceof operator checks whether an object is an instance of a particular class or interface. It returns true or false.

Java
// Traditional instanceof
if (obj instanceof String) {
    String s = (String) obj;  // manual cast
    System.out.println(s.toUpperCase());
}

// Java 16+ Pattern Matching
if (obj instanceof String s) {  // automatic cast into s
    System.out.println(s.toUpperCase());
}
Java
// Practical example with Shape hierarchy
public static void describeShape(Shape shape) {
    if (shape instanceof Circle c) {
        System.out.println("Circle with radius: " + c.radius);
    } else if (shape instanceof Rectangle r) {
        System.out.println("Rectangle: " + r.length + "x" + r.width);
    } else if (shape instanceof Triangle t) {
        System.out.println("Triangle base: " + t.base);
    }
}

9. The final Keyword — Variable, Method, Class

UsageMeaningExample
final variableValue cannot be changed (constant)final double PI = 3.14159;
final methodCannot be overridden by child classfinal void validate() { }
final classCannot be extended (no child classes)final class String { }
Java
// final variable — constant
final double GST_RATE = 18.0;
// GST_RATE = 20.0;  // ❌ Compile Error!

// final method — cannot override
class BankAccount {
    public final void getAccountNumber() {
        System.out.println("ACC-12345");
    }
}

class SavingsAccount extends BankAccount {
    // @Override
    // public void getAccountNumber() { }  // ❌ Compile Error!
}

// final class — cannot extend
final class ImmutableConfig {
    private final String dbUrl;
    ImmutableConfig(String url) { this.dbUrl = url; }
}
// class ChildConfig extends ImmutableConfig { }  // ❌ Compile Error!

10. Covariant Return Types

Since Java 5, an overriding method can return a subclass of the return type declared in the parent method. This is called a covariant return type.

Java
class Animal {
    public Animal create() {
        return new Animal();
    }
}

class Dog extends Animal {
    @Override
    public Dog create() {   // Dog is subclass of Animal — OK!
        return new Dog();
    }
}

Full Code: BankAccount Hierarchy

Java
class BankAccount {
    protected String holder;
    protected double balance;
    protected String accNo;

    public BankAccount(String holder, String accNo, double balance) {
        this.holder = holder;
        this.accNo = accNo;
        this.balance = balance;
    }

    public void deposit(double amt) { balance += amt; }
    public void withdraw(double amt) {
        if (amt <= balance) balance -= amt;
        else System.out.println("Insufficient funds!");
    }

    public double calculateInterest() { return 0; }

    @Override
    public String toString() {
        return holder + " [" + accNo + "] Balance: ₹" + balance;
    }
}

class SavingsAccount extends BankAccount {
    private double interestRate;

    public SavingsAccount(String h, String a, double b, double rate) {
        super(h, a, b);
        this.interestRate = rate;
    }

    @Override
    public double calculateInterest() {
        return balance * interestRate / 100;
    }
}

class CurrentAccount extends BankAccount {
    private double overdraftLimit;

    public CurrentAccount(String h, String a, double b, double odLimit) {
        super(h, a, b);
        this.overdraftLimit = odLimit;
    }

    @Override
    public void withdraw(double amt) {
        if (amt <= balance + overdraftLimit) balance -= amt;
        else System.out.println("Exceeds overdraft limit!");
    }

    @Override
    public double calculateInterest() { return 0; }
}

public class BankDemo {
    public static void main(String[] args) {
        BankAccount[] accounts = {
            new SavingsAccount("Rahul", "SB001", 50000, 4.5),
            new CurrentAccount("Priya Corp", "CA001", 100000, 25000)
        };

        for (BankAccount acc : accounts) {
            System.out.println(acc);
            System.out.println("Interest: ₹" + acc.calculateInterest());
            System.out.println();
        }
    }
}
Rahul [SB001] Balance: ₹50000.0 Interest: ₹2250.0 Priya Corp [CA001] Balance: ₹100000.0 Interest: ₹0.0

Full Code: Swing JFrame Extension

Java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class CustomFrame extends JFrame {
    private JLabel statusLabel;

    public CustomFrame() {
        super("My Custom Frame — Inheritance Demo");
        setSize(500, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new FlowLayout());

        JButton btn = new JButton("Click Me");
        statusLabel = new JLabel("Status: Waiting...");

        btn.addActionListener(e -> statusLabel.setText("Button Clicked!"));

        add(btn);
        add(statusLabel);
        setVisible(true);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.setColor(Color.BLUE);
        g.drawString("Custom painted text via overridden paint()", 50, 350);
    }

    public static void main(String[] args) {
        new CustomFrame();
    }
}
Section D

Learn by Doing — 3-Tier Lab Structure

🟢 Tier 1 — GUIDED: Build BankAccount → SavingsAccount

⏱️ 45–60 minutesBeginnerStep-by-step with full code

Step 1: Create BankAccount.java

Create a parent class with holder, balance, deposit(), withdraw(), and toString().

Step 2: Create SavingsAccount.java

Extend BankAccount. Add interestRate. Use super() in constructor. Override calculateInterest().

Step 3: Create TestBank.java

Create SavingsAccount objects, deposit money, calculate interest, display using toString().

Step 4: Test Dynamic Dispatch

Create a BankAccount reference holding a SavingsAccount object. Call calculateInterest() and observe polymorphism.

🎉 Congratulations! You've implemented single inheritance with method overriding and dynamic dispatch.

🟡 Tier 2 — SEMI-GUIDED: Add CurrentAccount & FixedDepositAccount

⏱️ 60–90 minutesIntermediateHints provided, you write the code

Your Mission:

Extend your Tier 1 code. Add CurrentAccount (with overdraft) and FixedDepositAccount (with maturity period). Use an array of BankAccount[] and iterate polymorphically.

Hints:

  1. CurrentAccount: Override withdraw() to allow overdraft up to a limit
  2. FixedDepositAccount: Override withdraw() to block withdrawal before maturity
  3. Use instanceof to print account-type-specific details
  4. Override toString() in each child class
Stretch Goal: Add a getAccountType() method using covariant return types — parent returns String, children return more specific strings.

🔴 Tier 3 — OPEN CHALLENGE: Complete Banking System

⏱️ 2–3 hoursAdvancedNo instructions — build from scratch

The Brief:

Build a menu-driven Banking System that supports: creating accounts (Savings/Current/FD), depositing, withdrawing, calculating interest, displaying all accounts, and searching by account number. Use ArrayList<BankAccount> and polymorphic operations throughout.

Deliverable: A working Java program with proper inheritance hierarchy, at least 3 account types, and polymorphic method calls.

Section E

Problem Set — Syntax, Programming & Interview Questions

Syntax / Output Tracing (5 Questions)

E1. What is the output?

Java
class A { void show() { System.out.print("A "); } }
class B extends A { void show() { System.out.print("B "); } }
class C extends B { void show() { System.out.print("C "); } }
// In main: A obj = new C(); obj.show();

Answer: C — Dynamic dispatch resolves to the actual object type (C).

E2. Does this compile? Why or why not?

Java
class Parent { protected void greet() { } }
class Child extends Parent { private void greet() { } }

Answer: No — private is more restrictive than protected. Violates overriding rule #4.

E3. What is the output?

Java
class X { X() { System.out.print("X "); } }
class Y extends X { Y() { System.out.print("Y "); } }
class Z extends Y { Z() { System.out.print("Z "); } }
// In main: Z obj = new Z();

Answer: X Y Z — Constructors chain from top to bottom. Parent constructors run first.

E4. What is the output?

Java
class A { int x = 10; }
class B extends A { int x = 20; }
// In main: A obj = new B(); System.out.println(obj.x);

Answer: 10 — Variables are NOT polymorphic. obj.x resolves to A's x (reference type).

E5. Does this compile?

Java
final class Immutable { }
class Child extends Immutable { }

Answer: No — Cannot extend a final class.

Programming Questions (8)

P1. Create an Employee hierarchy: EmployeeManager, Developer, Intern. Override calculateSalary() in each.

P2. Build a Vehicle hierarchy with Car, Bike, Truck. Override fuelEfficiency() method.

P3. Create a MediaPlayer class with play(). Extend it to AudioPlayer and VideoPlayer. Demonstrate dynamic dispatch.

P4. Implement a Library system: LibraryItemBook, Magazine, DVD. Override getLateFee(int days).

P5. Write a class where you override toString(), equals(), and hashCode() for a Product class.

P6. Demonstrate the difference between method overloading and overriding in a single program.

P7. Create a final class Constants with all final static variables for GST rates (5%, 12%, 18%, 28%).

P8. Build a program that uses instanceof with pattern matching (Java 16+) to process different shape types.

Industry-Level Questions (3)

I1. Design a notification system for an e-commerce platform (like Flipkart) where Notification is the parent class and EmailNotification, SMSNotification, PushNotification override send().

I2. Implement a tax calculation system where TaxCalculator is the base class and IncomeTaxCalc, GSTCalc, ProfessionalTaxCalc override calculateTax(double amount).

I3. Design a logging framework where Logger has log(String message) and children FileLogger, ConsoleLogger, DatabaseLogger override it.

Interview Questions (3)

IV1. Asked at Infosys SE Explain the Liskov Substitution Principle (LSP). Give an example where it is violated and how to fix it.

Expected: "If S is a subtype of T, then objects of type T may be replaced with objects of type S without altering the correctness of the program." Classic violation: Square extends Rectangle where setWidth() changes height too.

IV2. Asked at TCS Digital What is the difference between == and equals()? When would you override equals()?

IV3. Asked at Samsung R&D Explain dynamic method dispatch. Can it work with static methods? Why or why not?

Section F

MCQ Assessment Bank — 30 Questions (Bloom's Mapped)

Remember / Identify (Q1–Q5)

Q1

Which keyword is used to inherit a class in Java?

  1. implements
  2. extends
  3. inherits
  4. super
Remember
✅ Answer: (B) extends — The extends keyword establishes an IS-A relationship between parent and child class.
Q2

Which type of inheritance is NOT supported in Java with classes?

  1. Single
  2. Multilevel
  3. Multiple
  4. Hierarchical
Remember
✅ Answer: (C) Multiple — Java does not support multiple inheritance with classes to avoid the diamond problem. Use interfaces instead.
Q3

The super keyword is used to:

  1. Access parent class members only
  2. Call parent constructor only
  3. Access parent variable, method, and constructor
  4. Create parent class objects
Remember
✅ Answer: (C) — super has 3 uses: access parent variable (super.x), call parent method (super.method()), and call parent constructor (super(args)).
Q4

Which annotation helps catch method overriding errors at compile time?

  1. @Overload
  2. @Override
  3. @Inherited
  4. @Polymorphic
Remember
✅ Answer: (B) @Override — This annotation tells the compiler you intend to override a parent method. If the method signature doesn't match, it produces a compile error.
Q5

Every class in Java is a child of which class?

  1. System
  2. Main
  3. Object
  4. Base
Remember
✅ Answer: (C) Object — Every class implicitly extends java.lang.Object, which provides toString(), equals(), hashCode(), etc.

Understand / Explain (Q6–Q10)

Q6

Why does Java not support multiple inheritance with classes?

  1. Performance reasons
  2. Diamond problem — ambiguity in method resolution
  3. Memory limitations
  4. It was removed in Java 8
Understand
✅ Answer: (B) — If class C extends both A and B, and both have the same method, the compiler can't decide which to inherit. This ambiguity is the diamond problem.
Q7

In method overriding, the access modifier of the child method:

  1. Must be the same as parent
  2. Can be more restrictive
  3. Cannot be more restrictive than the parent
  4. Must always be public
Understand
✅ Answer: (C) — The access level can be the same or less restrictive. If parent has protected, child can be protected or public, but NOT private.
Q8

What is dynamic method dispatch?

  1. Calling methods at compile time based on reference type
  2. The JVM decides which overridden method to call at runtime based on actual object type
  3. Using reflection to invoke methods
  4. Calling static methods through inheritance
Understand
✅ Answer: (B) — When a parent reference holds a child object, the JVM checks the actual object type at runtime to determine which overridden method to execute.
Q9

What does final mean when applied to a method?

  1. The method runs last
  2. The method cannot be overridden by child classes
  3. The method is static
  4. The method returns a constant
Understand
✅ Answer: (B) — A final method cannot be overridden in any subclass. This is useful for security-critical methods like authentication.
Q10

What is a covariant return type?

  1. Returning a parent class type when overriding
  2. Returning a subclass of the parent's return type when overriding
  3. Returning void in overridden methods
  4. Returning the same type in all methods
Understand
✅ Answer: (B) — Since Java 5, an overriding method can return a subclass of the original return type. E.g., parent returns Animal, child returns Dog.

Apply (Q11–Q15)

Q11

Given: class A { void show() { print("A"); } } and class B extends A { void show() { print("B"); } }. What does A obj = new B(); obj.show(); print?

  1. A
  2. B
  3. AB
  4. Compile error
Apply
✅ Answer: (B) — Dynamic dispatch. The actual object is B, so B's show() is called despite the reference type being A.
Q12

What is the output? class P { P() { print("P "); } } class Q extends P { Q() { print("Q "); } } and new Q();

  1. Q P
  2. P Q
  3. P
  4. Q
Apply
✅ Answer: (B) P Q — Parent constructor always executes before child constructor. super() is implicitly called.
Q13

Which line causes a compile error?

class Animal { public void eat() { } }
class Dog extends Animal {
    @Override
    protected void eat() { }  // Line X
}
  1. No error
  2. Line X — more restrictive access
  3. Error in Animal class
  4. @Override is wrong
Apply
✅ Answer: (B) — Parent's eat() is public, child tries protected which is more restrictive. Violates overriding rule #4.
Q14

Given class A { int x = 5; } class B extends A { int x = 10; }. What does A obj = new B(); print(obj.x); output?

  1. 5
  2. 10
  3. 15
  4. Compile error
Apply
✅ Answer: (A) 5 — Instance variables are NOT polymorphic. The reference type (A) determines which variable is accessed.
Q15

What does obj instanceof String return if obj is null?

  1. true
  2. false
  3. NullPointerException
  4. Compile error
Apply
✅ Answer: (B) false — instanceof returns false when the reference is null, never throws NullPointerException.

Analyze (Q16–Q20)

Q16

In a Shape hierarchy, why is it better to declare area() as abstract in the parent rather than returning 0?

  1. Performance optimization
  2. Forces every child to provide its own implementation — prevents forgetting
  3. It uses less memory
  4. Java requires it
Analyze
✅ Answer: (B) — An abstract method forces child classes to override it. If you just return 0, a child could accidentally skip the override and silently return wrong results.
Q17

Why can't static methods be overridden?

  1. They are always final
  2. They belong to the class, not to objects — no dynamic dispatch
  3. Static methods can't access instance variables
  4. Java doesn't allow static in child classes
Analyze
✅ Answer: (B) — Static methods are resolved at compile time based on reference type (static binding). Dynamic dispatch works only with instance methods.
Q18

Compare: method overloading vs method overriding. Which statement is TRUE?

  1. Both require inheritance
  2. Overloading changes parameters; overriding keeps them the same
  3. Both are resolved at runtime
  4. Overriding can change the parameter list
Analyze
✅ Answer: (B) — Overloading: same name, different parameters (compile-time). Overriding: same name AND same parameters (runtime).
Q19

What happens when you override equals() but NOT hashCode()?

  1. No impact
  2. Objects may not work correctly in HashSet and HashMap
  3. Compile error
  4. Runtime exception
Analyze
✅ Answer: (B) — The contract says: if a.equals(b) is true, then a.hashCode() == b.hashCode() must also be true. Breaking this causes bugs in hash-based collections.
Q20

Which is true about constructor chaining in multilevel inheritance (A → B → C)?

  1. C's constructor runs first
  2. A's constructor runs first, then B's, then C's
  3. Only C's constructor runs
  4. Order is random
Analyze
✅ Answer: (B) — Constructors execute top-down: A first, then B, then C. Each child's constructor calls super() before its own body.

Evaluate (Q21–Q25)

Q21

A team makes BankAccount a final class. Is this good design for a banking system?

  1. Yes — prevents tampering
  2. No — prevents creating SavingsAccount, CurrentAccount subclasses
  3. Depends on the database
  4. final doesn't affect inheritance
Evaluate
✅ Answer: (B) — Making BankAccount final prevents any specialization. A banking system needs SavingsAccount, CurrentAccount, etc. Better to make specific methods final instead.
Q22

Which violates the Liskov Substitution Principle?

  1. Dog extends Animal and overrides eat() to eat differently
  2. Square extends Rectangle but setWidth() also changes height
  3. SavingsAccount extends BankAccount and adds calculateInterest()
  4. Circle extends Shape and overrides area()
Evaluate
✅ Answer: (B) — A Square that changes both dimensions when you set one breaks the Rectangle contract. A Rectangle user expects setWidth() to only change width.
Q23

Is it good practice to catch all exceptions using catch(Exception e) in overridden methods?

  1. Yes — handles everything
  2. No — too broad, hides specific errors, makes debugging harder
  3. Yes — improves performance
  4. It doesn't compile
Evaluate
✅ Answer: (B) — Catching generic Exception hides specific bugs. Always catch the most specific exception type.
Q24

Should toString() be overridden in every class?

  1. No — it's unnecessary overhead
  2. Yes — meaningful string representation aids debugging, logging, and display
  3. Only in final classes
  4. Only when using databases
Evaluate
✅ Answer: (B) — Default toString() returns ClassName@hash which is useless. Overriding it makes debugging, logging, and unit testing much easier.
Q25

Using protected access for parent class fields (like balance) is:

  1. Always bad — use private
  2. Good when child classes need direct access, but be aware it widens visibility to the package
  3. Same as public
  4. Same as private
Evaluate
✅ Answer: (B) — protected grants access to child classes (even in different packages) AND all classes in the same package. It's a trade-off between encapsulation and child-class convenience.

Create (Q26–Q30)

Q26

To design a notification system where Email, SMS, and Push notifications each send differently, you should:

  1. Use three unrelated classes
  2. Create an abstract Notification class with abstract send() and extend it
  3. Put all logic in one class with if-else
  4. Use static methods
Create
✅ Answer: (B) — Abstract parent with abstract method forces each child to implement its own send(). Polymorphism then allows processing any notification type uniformly.
Q27

How would you design an immutable configuration class?

  1. Make all fields public
  2. Make the class final, all fields private final, no setters, set values in constructor
  3. Use protected fields
  4. Override equals() only
Create
✅ Answer: (B) — final class prevents extension, private final fields prevent modification, constructor sets all values, no setters. This is the immutable class pattern.
Q28

To implement a Shape drawing application where new shapes can be added without modifying existing code, you should use:

  1. Switch-case with shape types
  2. Abstract Shape class with abstract draw() — new shapes just extend and override
  3. Static utility methods
  4. String-based shape names
Create
✅ Answer: (B) — The Open-Closed Principle: open for extension (new shapes), closed for modification (existing code unchanged). Polymorphism makes this possible.
Q29

You need a Swing GUI with a custom JFrame that draws shapes. The best approach is:

  1. Create a separate class and use JFrame as a field
  2. Extend JFrame, override paint(Graphics g), call super.paint(g) first
  3. Use only AWT, not Swing
  4. Override main() instead
Create
✅ Answer: (B) — Extending JFrame and overriding paint() is the standard way to create custom Swing frames. Always call super.paint(g) first to clear the canvas.
Q30

To create a banking system that supports future account types without changing existing code, you should:

  1. Use a single class with type flags
  2. Define abstract BankAccount with abstract methods, add new types by extending
  3. Use arrays of primitives
  4. Avoid inheritance entirely
Create
✅ Answer: (B) — Abstract BankAccount with abstract calculateInterest(), withdraw(). New account types extend and provide their implementation. Existing code using BankAccount references works without modification.
Section G

Short Answer Questions (8)

SA1. What is inheritance in Java? Name the types supported.

Expected: Inheritance is the mechanism where a child class acquires properties and methods of a parent class using extends. Types: Single, Multilevel, Hierarchical. Multiple inheritance is NOT supported with classes (use interfaces).

SA2. What are the 3 uses of the super keyword?

Expected: (1) Access parent's variable: super.variableName. (2) Call parent's method: super.methodName(). (3) Call parent's constructor: super(args) — must be first statement in child constructor.

SA3. List the 5 rules of method overriding.

Expected: Same method name, same parameters, IS-A relationship required, access modifier can't be more restrictive, return type must be same or covariant.

SA4. What is the difference between method overloading and overriding?

Expected: Overloading: same name, different parameters, same class, compile-time binding. Overriding: same name, same parameters, parent-child relationship, runtime binding.

SA5. Why should you override hashCode() when you override equals()?

Expected: The contract states: if a.equals(b) is true, their hash codes must be equal. Breaking this makes objects behave incorrectly in HashMap and HashSet.

SA6. What is dynamic method dispatch?

Expected: When a parent reference holds a child object and calls an overridden method, the JVM resolves the call at runtime based on the actual object type, not the reference type.

SA7. What is the diamond problem?

Expected: If class C extends both A and B (both having method show()), the compiler can't determine which show() C inherits. Java avoids this by prohibiting multiple inheritance with classes.

SA8. Explain final keyword with variable, method, and class.

Expected: final variable = constant (value can't change). final method = can't be overridden. final class = can't be extended. Example: String is a final class.

Section H

Long Answer Questions (3)

LA1. Explain inheritance in Java with types, syntax, and a complete code example showing multilevel inheritance with constructor chaining.

Expected Answer (key points): Define inheritance, IS-A relationship, extends keyword. Explain single, multilevel, hierarchical types. Discuss diamond problem for why no multiple inheritance. Show complete code: Animal → Dog → Puppy with constructors using super(). Show output demonstrating constructor chaining order (A→B→C). Mention protected/public access for inherited members.

LA2. Differentiate between compile-time and runtime polymorphism. Demonstrate runtime polymorphism with a complete Shape hierarchy program including dynamic method dispatch.

Expected Answer (key points): Define polymorphism. Compare overloading (compile-time, same class, different params) vs overriding (runtime, parent-child, same signature). Write complete Shape → Circle, Rectangle, Triangle with area() override. Create Shape[] array with child objects. Show polymorphic loop calling area(). Explain how JVM resolves at runtime. Mention @Override annotation.

LA3. Explain the Object class in Java. Why is it important? Demonstrate overriding toString(), equals(), and hashCode() in a Student class.

Expected Answer (key points): Every class extends Object implicitly. List methods: toString, equals, hashCode, getClass, clone, finalize, wait, notify. Explain default behaviour of each. Show Student class overriding all three. Explain equals-hashCode contract. Show usage with System.out.println (toString), if-comparison (equals), and HashMap (hashCode). Mention that getClass() is final.

Section I

Lab Programs — Lab 7 & Lab 8

🔬 Lab 7 — Inheritance Using Swing: JFrame → CustomFrame

⏱️ 90 minutesIntermediateSwing GUI with Inheritance

Objective:

Create a custom GUI application by extending JFrame. Override paint() to draw custom shapes. Add interactive buttons using event listeners.

Complete Code:

Java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class CustomFrame extends JFrame {
    private JLabel statusLabel;
    private JTextField nameField;
    private String greeting = "Welcome to EduArtha!";
    private Color shapeColor = Color.BLUE;

    public CustomFrame() {
        super("Lab 7 — Custom JFrame with Inheritance");
        setSize(600, 500);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new FlowLayout(10));

        // Components
        JLabel nameLabel = new JLabel("Enter your name:");
        nameField = new JTextField(15);
        JButton greetBtn = new JButton("Greet Me");
        JButton colorBtn = new JButton("Change Color");
        statusLabel = new JLabel("Status: Ready");

        // Event listeners
        greetBtn.addActionListener(e -> {
            String name = nameField.getText();
            if (!name.isEmpty()) {
                greeting = "Hello, " + name + "! Welcome to Java!";
                statusLabel.setText("Greeted: " + name);
                repaint();
            }
        });

        colorBtn.addActionListener(e -> {
            shapeColor = (shapeColor == Color.BLUE) ? Color.RED : Color.BLUE;
            repaint();
        });

        add(nameLabel);
        add(nameField);
        add(greetBtn);
        add(colorBtn);
        add(statusLabel);
        setVisible(true);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);

        // Draw shapes using inheritance-overridden paint()
        g.setColor(shapeColor);
        g.fillOval(50, 150, 100, 100);
        g.fillRect(200, 150, 120, 80);

        // Draw greeting text
        g.setColor(Color.BLACK);
        g.setFont(new Font("Arial", Font.BOLD, 16));
        g.drawString(greeting, 50, 320);

        g.setColor(Color.GRAY);
        g.setFont(new Font("Arial", Font.ITALIC, 12));
        g.drawString("Drawn via overridden paint() — Inheritance in action!", 50, 380);
    }

    public static void main(String[] args) {
        new CustomFrame();
    }
}

Viva Questions — Lab 7

V1. Why does CustomFrame extend JFrame instead of creating a JFrame object?

A: Extending JFrame establishes IS-A relationship — CustomFrame IS-A JFrame. This allows overriding paint() for custom drawing, which is not possible with composition (HAS-A).

V2. Why must super.paint(g) be called first inside paint()?

A: It clears the canvas and repaints child components. Without it, old drawings persist and the GUI looks corrupted.

V3. What type of polymorphism is demonstrated when JFrame's paint() is overridden?

A: Runtime polymorphism (dynamic dispatch). The JVM calls CustomFrame's paint() even though the Swing framework internally references it as JFrame.

V4. Can we use super() inside a method?

A: No. super() (constructor call) can only be used inside a constructor. super.method() can be used in any instance method.

V5. What happens if we remove setDefaultCloseOperation(EXIT_ON_CLOSE)?

A: Clicking the X button hides the window but the JVM process keeps running in the background. EXIT_ON_CLOSE ensures the program terminates.

Extension: Add a JComboBox to select shapes (Circle, Rectangle, Triangle). Override paint() to draw the selected shape. Add JSlider for size control.

🔬 Lab 8 — Polymorphism with Access Control

⏱️ 90 minutesIntermediateMethod Overriding + Access Modifiers

Objective:

Demonstrate runtime polymorphism with method overriding while exploring access modifier rules. Show how access levels affect overriding.

Complete Code:

Java
// Base class — Employee
class Employee {
    private String name;
    protected double baseSalary;

    public Employee(String name, double salary) {
        this.name = name;
        this.baseSalary = salary;
    }

    public String getName() { return name; }

    // protected — can be widened to public in child
    protected double calculatePay() {
        return baseSalary;
    }

    // public — child must keep public
    public String getRole() {
        return "Employee";
    }

    // final — cannot be overridden
    public final void displayId() {
        System.out.println("EMP-" + hashCode());
    }

    @Override
    public String toString() {
        return getRole() + ": " + name + " | Pay: ₹" + calculatePay();
    }
}

// Manager — widens access from protected to public
class Manager extends Employee {
    private double bonus;

    public Manager(String name, double salary, double bonus) {
        super(name, salary);
        this.bonus = bonus;
    }

    @Override
    public double calculatePay() {  // widened: protected → public ✅
        return baseSalary + bonus;
    }

    @Override
    public String getRole() { return "Manager"; }
}

// Developer — uses super to add to parent's calculation
class Developer extends Employee {
    private int overtimeHours;

    public Developer(String name, double salary, int otHours) {
        super(name, salary);
        this.overtimeHours = otHours;
    }

    @Override
    public double calculatePay() {
        return super.calculatePay() + (overtimeHours * 500);
    }

    @Override
    public String getRole() { return "Developer"; }
}

// Intern — minimal override
class Intern extends Employee {
    public Intern(String name, double stipend) {
        super(name, stipend);
    }

    @Override
    public String getRole() { return "Intern"; }
}

// Main class
public class PayrollSystem {
    public static void main(String[] args) {
        Employee[] team = {
            new Manager("Anita Desai", 80000, 20000),
            new Developer("Raj Kumar", 60000, 25),
            new Intern("Sneha Patil", 15000)
        };

        System.out.println("===== Payroll Report =====");
        double totalPayroll = 0;

        for (Employee emp : team) {
            System.out.println(emp);  // calls overridden toString()
            emp.displayId();       // final method — same in all
            totalPayroll += emp.calculatePay();
            System.out.println();
        }

        System.out.println("Total Payroll: ₹" + totalPayroll);

        // instanceof demo
        for (Employee emp : team) {
            if (emp instanceof Manager m) {
                System.out.println(m.getName() + " gets manager benefits");
            }
        }
    }
}
===== Payroll Report ===== Manager: Anita Desai | Pay: ₹100000.0 EMP-12345678 Developer: Raj Kumar | Pay: ₹72500.0 EMP-87654321 Intern: Sneha Patil | Pay: ₹15000.0 EMP-11223344 Total Payroll: ₹187500.0 Anita Desai gets manager benefits

Viva Questions — Lab 8

V1. Can Manager's calculatePay() have private access? Why not?

A: No. Parent has protected. Child can widen (protected → public) but not restrict (protected → private). That violates overriding rule #4.

V2. What would happen if we try to override displayId() in Manager?

A: Compile error. displayId() is final in Employee, so it cannot be overridden in any child class.

V3. Why does emp.calculatePay() call different methods for different employees?

A: Dynamic method dispatch. Although the reference type is Employee, the JVM checks the actual object type at runtime and calls the corresponding overridden method.

V4. Why is baseSalary declared as protected and not private?

A: protected allows direct access in child classes (Manager, Developer). If private, children would need getter methods, adding boilerplate.

V5. How does toString() in Employee call the correct getRole() for each child?

A: toString() calls getRole() which is overridden in each child. Since this refers to the actual object, dynamic dispatch ensures the correct child version runs.

Extension: Add a ContractEmployee with hourly rate. Override calculatePay() to compute hourly × hours worked. Add a method isEligibleForPF() that uses instanceof to check if employee qualifies.
Section J

Industry Spotlight — A Day in the Life

👨‍💻 Deepak Verma, 29 — Software Engineer at Samsung R&D, Bangalore

Background: B.Tech from NIT Bhopal. Started with Java in 2nd year. Built an inventory management desktop app for his father's textile shop in Indore as a college project. Got placed at Samsung through campus recruitment. Now works on Samsung's One UI framework team — the interface layer on Galaxy phones.

A Typical Day:

9:00 AM — Standup with the One UI team. Review Jira tickets for new features on the Settings app. The Settings app uses deep class hierarchies — every settings page extends BaseSettingsFragment.

10:00 AM — Implementing a new Battery Settings page. Creates BatterySettingsFragment extends BaseSettingsFragment. Overrides onCreatePreferences() and onPreferenceClick().

12:00 PM — Code review. Senior points out a Liskov Substitution violation — a child class throws an exception the parent never declared. Deepak refactors.

2:00 PM — Lunch at Samsung's Bangalore campus cafeteria. Discusses design patterns with teammates.

3:00 PM — Unit testing. Uses JUnit with polymorphic mocks — SettingsFragment mockFragment = new MockBatterySettings(); Dynamic dispatch ensures mock methods are called.

5:30 PM — Personal learning — studying Kotlin coroutines (Samsung is migrating some Java code to Kotlin).

DetailInfo
Tools Used DailyJava, Kotlin, Android Studio, Git, Jira, Jenkins CI/CD
Entry Salary (2024)₹8–12 LPA + benefits
Mid-Level (3–5 yrs)₹15–25 LPA
Senior (7+ yrs)₹30–50 LPA
Companies HiringSamsung R&D, Google, Microsoft, Amazon, Flipkart, Paytm, PhonePe, Adobe, Uber, Ola
Section K

Earn With It — OOP Desktop Apps

💰 Your Earning Path After This Unit

Portfolio Piece: "Java Banking System" — a Swing-based desktop application with inheritance hierarchy, polymorphic operations, and custom GUI built by extending JFrame.

Beginner Gig Ideas:

• Inventory Management Desktop App for small shops — ₹5,000–₹15,000

• Student Result Management System for coaching centres — ₹4,000–₹10,000

• Billing/Invoice Generator with OOP hierarchy — ₹3,000–₹8,000

• Library Management System for schools — ₹5,000–₹12,000

PlatformBest ForTypical Rate
InternshalaIndian student Java projects₹5,000–₹15,000/project
FiverrGlobal clients, Java desktop apps$25–$100/gig (₹2K–₹8K)
UpworkLonger Java projects$15–$50/hour
Local BusinessesShops, schools, clinics in your area₹5,000–₹20,000/project

⏱️ Time to First Earning: 3–4 weeks (complete Labs 7-8, build one portfolio app, create Internshala profile)

Your father's shop, your college canteen, your coaching centre — they all need inventory/billing software. Build it using the BankAccount pattern you learned here. Replace BankAccount with Product, SavingsAccount with FoodItem, CurrentAccount with StationaryItem. Same inheritance, different domain. That's your first ₹10K project.
Section L

Chapter Summary & Code Tweet

📝 Key Takeaways — Unit 8

Inheritance = child class acquires parent's properties using extends. Types: Single, Multilevel, Hierarchical.

No multiple inheritance with classes (diamond problem). Use interfaces.

super = 3 uses: parent variable, parent method, parent constructor (must be first statement).

Method Overriding = same name + same params + IS-A + access not more restrictive + covariant return.

@Override = compiler-checked safety net for overriding.

Object class = mother of all classes. Override toString(), equals(), hashCode().

Polymorphism = Compile-time (overloading) + Runtime (overriding via dynamic dispatch).

Dynamic Method Dispatch = parent ref + child object → child's method runs at runtime.

instanceof = type checking. Java 16+ adds pattern matching for cleaner code.

final = variable (constant), method (no override), class (no extend).

Covariant return types = child can return subclass of parent's return type.

Code Tweet (280 chars)

class Parent { void work() {} }
class Child extends Parent {
  @Override void work() { /* my way */ }
}
Parent ref = new Child();
ref.work(); // Child's version runs! 🎯
// That's dynamic dispatch. That's polymorphism. #Java
Section M

Earning Checkpoint — Unit 8 Readiness

Skill LearnedTool / TechniquePortfolio EvidenceEarn-Ready?
Inheritance HierarchyJava extendsBankAccount → SavingsAccount/CurrentAccount✅ Yes — core OOP skill
Method Overriding@Override annotationShape hierarchy with area() polymorphism✅ Yes — interview essential
Dynamic DispatchParent ref + child objectPaymentGateway polymorphic demo✅ Yes — used in all Java frameworks
Swing GUI (Lab 7)JFrame extensionCustomFrame with paint() override✅ Yes — desktop app foundation
Access Control (Lab 8)Access modifiers in overridingPayrollSystem with Employee hierarchy✅ Yes — real-world design pattern
Object class methodstoString, equals, hashCodeStudent class with proper overrides✅ Yes — asked in 90% of interviews
final keywordfinal class/method/variableImmutableConfig example✅ Yes — security-critical code
Minimum Viable Earning Setup after this unit: A Java Swing desktop app in your GitHub + Internshala profile with "Java OOP Developer" tag + 2 portfolio projects (Banking System + GUI App) = you can earn ₹10,000–₹30,000/month from desktop app projects while in college.

✅ Unit 8 complete. MCQs: 30. Labs 7,8 covered. Ready for Unit 9!

[QR: Link to EduArtha video tutorial — Java Inheritance & Polymorphism]