☕ Java Backend Course

Inheritance in Java
Complete Deep Dive

OOP ka sabse important pillar — Theory, Memory Model, Method Overriding, super keyword, Abstract Classes, Interfaces, Polymorphism — ek hi jagah, depth mein.

10
Chapters
50+
Code Examples
40+
Practice Programs
4
OOP Pillars
Full
Theory Covered
01

Inheritance Kya Hai?

Core Concept · Real-World Analogy · Why Inheritance · IS-A Relationship · Memory Model

📖 Core Definition

Ek Class Doosri Class Ka Sab Kuch Le Le — Inheritance

Inheritance ek OOP mechanism hai jisme ek class (child / subclass / derived class) doosri class (parent / superclass / base class) ke properties aur methods ko inherit karti hai — matlab bina dobara likhey use kar sakti hai.

Real-world analogy: Baap ke paas ghar, gaadi, properties hain — beta automatically unka malik ban jaata hai (inherit karta hai). Beta apni nai properties bhi add kar sakta hai aur baap ki kuch baatein change bhi kar sakta hai (override). Yehi inheritance hai.

Java mein keyword hai extends — child class parent class ko extend karti hai. Ek child ke sirf ek parent ho sakta hai (single inheritance), but ek parent ke multiple children ho sakte hain.

Formal Definition: Inheritance is an OOP mechanism where a subclass acquires the properties (fields) and behaviors (methods) of a superclass, enabling code reuse, hierarchical classification, and IS-A relationship modeling. In Java, implemented via the extends keyword.
🔗 IS-A Relationship — Sabse Zaroori Check

Kab Inheritance Use Karein?

Inheritance sirf tab use karo jab IS-A relationship ho. Test karo: "Kya [Child] ek [Parent] hai?"

  • Dog IS-A Animalclass Dog extends Animal — CORRECT
  • Car IS-A Vehicleclass Car extends Vehicle — CORRECT
  • SavingsAccount IS-A BankAccount → CORRECT
  • Engine IS-A Car → Engine car nahi hai, car ke PAAS engine hai — ye HAS-A hai, Composition use karo
  • Student IS-A School → WRONG — student school mein JAATA hai, school nahi hai

IS-A = Inheritance. HAS-A = Composition (object as field).

⚡ Inheritance Ke Fayde

Code Reuse + Extensibility

  • Code Reuse: Parent class mein likha hua code baar baar nahi likhna padta. 100 animal types ke liye common `eat()`, `breathe()` sirf ek baar Animal mein
  • Extensibility: Naye types add karna aasaan — sirf nai class banao aur extend karo
  • Polymorphism: Ek Animal reference se Dog, Cat, Horse sab ko point kar sakte ho — runtime pe decide hota hai
  • Maintenance: Parent class mein bug fix karo — sab children automatically fix ho jaate hain
  • Hierarchy Modeling: Real-world hierarchies ko cleanly represent karo
Inheritance Hierarchy — Animal Example
Parent (Superclass)Animal
↓ extends ↓
Child (Subclass)Dog
Child (Subclass)Cat
Child (Subclass)Bird
↓ extends ↓
GrandchildLabrador
GrandchildPersian
GrandchildParrot
Labrador IS-A Dog IS-A Animal · Labrador ko Animal ke sare fields/methods milte hain automatically · extends chain se
🔑

extends

Java keyword jo inheritance declare karta hai. class Dog extends Animal

👪

Parent / Super

Jis class se properties milti hain. Base class ya Superclass bhi kehte hain.

👶

Child / Sub

Jo class inherit karti hai. Subclass ya Derived class bhi kehte hain.

🔄

Code Reuse

Parent mein likha code child mein dobara likhne ki zaroorat nahi.

🚫

Private Members

Parent ke private fields/methods child inherit nahi kar sakta. protected karo.

🏛️

Object Class

Java mein har class implicitly Object ko extend karti hai — root of all classes.

💻 Code Examples
EX 1.1

Pehla Inheritance Program — Animal aur Dog

Sabse basic example — parent class Animal, child class Dog. Kya inherit hota hai, kya nahi — clearly samjho.
// ── PARENT CLASS ──────────────────────────────────
class Animal {
    // Fields — instance variables
    String name;
    int    age;
    String color;

    // Constructor
    Animal(String name, int age, String color) {
        this.name  = name;
        this.age   = age;
        this.color = color;
    }

    // Methods — behaviours
    void eat() {
        System.out.println(name + " khaana kha raha hai 🍖");
    }

    void breathe() {
        System.out.println(name + " saans le raha hai 💨");
    }

    void sleep() {
        System.out.println(name + " so raha hai 😴");
    }

    void showInfo() {
        System.out.println("Name: " + name + " | Age: " + age + " | Color: " + color);
    }
}

// ── CHILD CLASS ─────────────────────────────────────
// Dog ko Animal ke SARE non-private members mil jaate hain
// Dog khud ka kuch extra bhi add karta hai
class Dog extends Animal {
    // Dog ka apna extra field
    String breed;

    Dog(String name, int age, String color, String breed) {
        // Animal ka constructor call karo pehle (super)
        super(name, age, color);
        this.breed = breed;
    }

    // Dog ka apna extra method
    void bark() {
        System.out.println(name + " bol raha hai: Bhow Bhow! 🐕");
    }

    void fetch() {
        System.out.println(name + " ball fetch kar raha hai 🎾");
    }
}

public class InheritanceBasic {
    public static void main(String[] args) {
        // Dog object banao
        Dog dog = new Dog("Bruno", 3, "Brown", "Labrador");

        // ✅ Inherited from Animal — seedha use karo
        dog.showInfo();   // Animal ka method
        dog.eat();        // Animal ka method
        dog.breathe();    // Animal ka method
        dog.sleep();      // Animal ka method

        // ✅ Dog ke apne methods
        dog.bark();
        dog.fetch();

        System.out.println("Breed: " + dog.breed);

        System.out.println("\n--- instanceof check ---");
        System.out.println("dog instanceof Dog:    " + (dog instanceof Dog));
        System.out.println("dog instanceof Animal: " + (dog instanceof Animal));
        System.out.println("dog instanceof Object: " + (dog instanceof Object)); // hamesha true!
    }
}
▶ Output
Name: Bruno | Age: 3 | Color: Brown Bruno khaana kha raha hai 🍖 Bruno saans le raha hai 💨 Bruno so raha hai 😴 Bruno bol raha hai: Bhow Bhow! 🐕 Bruno ball fetch kar raha hai 🎾 Breed: Labrador --- instanceof check --- dog instanceof Dog: true dog instanceof Animal: true dog instanceof Object: true
EX 1.2

Vehicle → Car → ElectricCar — Multi-level + Access Control

3 level hierarchy + access modifiers ka effect — public, protected, private — kya inherit hota hai kya nahi.
class Vehicle {
    public    String brand;       // ✅ everywhere accessible
    protected int    speed;        // ✅ same package + subclasses
    private   String engineSerial; // ❌ ONLY this class
    String            type;         // ✅ default = same package

    Vehicle(String brand, int speed, String type) {
        this.brand = brand;
        this.speed = speed;
        this.type  = type;
        this.engineSerial = "ENG-001";  // private
    }

    public void move() { System.out.println(brand + " chal raha hai 🚗"); }
    public void stop() { System.out.println(brand + " ruk gaya 🛑"); }

    public String getSerial() { return engineSerial; } // getter via method
}

class Car extends Vehicle {
    int doors;

    Car(String brand, int speed, int doors) {
        super(brand, speed, "Car");
        this.doors = doors;
    }

    void honk() { System.out.println(brand + ": Beep Beep! 📯"); }

    void carInfo() {
        System.out.println("Brand: " + brand);        // ✅ public
        System.out.println("Speed: " + speed);        // ✅ protected — child access
        System.out.println("Type:  " + type);         // ✅ default (same package)
        System.out.println("Doors: " + doors);
        // System.out.println(engineSerial); // ❌ COMPILE ERROR — private!
        System.out.println("Serial (via getter): " + getSerial()); // ✅ method use karo
    }
}

class ElectricCar extends Car {
    int batteryKm;

    ElectricCar(String brand, int speed, int doors, int batteryKm) {
        super(brand, speed, doors);
        this.batteryKm = batteryKm;
    }

    void charge() { System.out.println(brand + " charging ho raha hai ⚡"); }

    void fullInfo() {
        System.out.println("=== Electric Car Info ===");
        System.out.println("Brand:   " + brand);
        System.out.println("Speed:   " + speed + " km/h");
        System.out.println("Doors:   " + doors);
        System.out.println("Battery: " + batteryKm + " km");
    }
}

public class MultiLevelInheritance {
    public static void main(String[] args) {
        ElectricCar tesla = new ElectricCar("Tesla", 250, 4, 500);

        tesla.move();     // Vehicle ka method
        tesla.stop();     // Vehicle ka method
        tesla.honk();     // Car ka method
        tesla.charge();   // ElectricCar ka method
        tesla.fullInfo();

        System.out.println("\n--- instanceof (chain check) ---");
        System.out.println("tesla instanceof ElectricCar: " + (tesla instanceof ElectricCar));
        System.out.println("tesla instanceof Car:         " + (tesla instanceof Car));
        System.out.println("tesla instanceof Vehicle:     " + (tesla instanceof Vehicle));
        System.out.println("tesla instanceof Object:      " + (tesla instanceof Object));
    }
}
▶ Output
Tesla chal raha hai 🚗 Tesla ruk gaya 🛑 Tesla: Beep Beep! 📯 Tesla charging ho raha hai ⚡ === Electric Car Info === Brand: Tesla Speed: 250 km/h Doors: 4 Battery: 500 km --- instanceof (chain check) --- tesla instanceof ElectricCar: true tesla instanceof Car: true tesla instanceof Vehicle: true tesla instanceof Object: true
02

extends Keyword

Constructor Chain · Object Class · What Gets Inherited · Access Rules

📖 Theory — extends Ka Kaam

extends Se Exactly Kya Hota Hai?

Jab aap class Dog extends Animal likhte ho, Java compiler internally ye kaam karta hai:

  1. Dog class ke object mein Animal ke sare non-private fields bhi allocate hote hain
  2. Animal ke sare non-private methods Dog ke objects pe automatically callable ho jaate hain
  3. Dog ka constructor automatically (implicitly) super() call karta hai — Animal ka no-arg constructor
  4. Dog IS-A Animal true ho jaata hai — Animal a = new Dog(...) valid ho jaata hai

Important: Java mein sirf single inheritance allowed hai (ek class sirf ek class extend kar sakti hai). Multiple inheritance interfaces se milti hai.

Memberpublicprotecteddefault (no mod)private
Same class
Same package subclass
Different package subclass
Different package non-subclass
⚠️
Private Members: Private fields/methods child class inherit nahi karti — ye parent class mein rahte hain. Child ke paas access nahi hota directly. Solution: protected use karo ya getters/setters banao.
EX 2.1

Constructor Chain — Automatically Calls Parent

Child ka constructor automatically parent ka default constructor call karta hai. Agar parent mein default constructor nahi, error aata hai. super() explicitly call karna zaroori ho jaata hai.
class GrandParent {
    GrandParent() {
        System.out.println("1️⃣  GrandParent() constructor called");
    }
}

class Parent extends GrandParent {
    Parent() {
        // Implicit super() — GrandParent() call hoga pehle
        System.out.println("2️⃣  Parent() constructor called");
    }
}

class Child extends Parent {
    Child() {
        // Implicit super() — Parent() call hoga pehle
        System.out.println("3️⃣  Child() constructor called");
    }
}

// ── What if parent has NO default constructor? ──
class Person {
    String name;
    int    age;

    // Sirf parameterized constructor — default (no-arg) nahi hai
    Person(String name, int age) {
        this.name = name;
        this.age  = age;
        System.out.println("Person(" + name + ", " + age + ") called");
    }

    void introduce() {
        System.out.println("Main " + name + " hoon, age " + age);
    }
}

class Student extends Person {
    String rollNo;
    double cgpa;

    Student(String name, int age, String rollNo, double cgpa) {
        super(name, age);  // MUST call — Person has no default constructor!
        this.rollNo = rollNo;
        this.cgpa   = cgpa;
        System.out.println("Student(" + rollNo + ") called");
    }

    void study() {
        System.out.println(name + " padh raha hai (CGPA: " + cgpa + ")");
    }
}

public class ConstructorChain {
    public static void main(String[] args) {
        System.out.println("=== Constructor Chain (GrandParent→Parent→Child) ===");
        Child c = new Child();  // Trace the chain!

        System.out.println("\n=== super() with parameterized constructor ===");
        Student s = new Student("Rahul", 20, "CS2024", 8.5);
        s.introduce();  // Person ka method
        s.study();      // Student ka method
    }
}
▶ Output
=== Constructor Chain (GrandParent→Parent→Child) === 1️⃣ GrandParent() constructor called 2️⃣ Parent() constructor called 3️⃣ Child() constructor called === super() with parameterized constructor === Person(Rahul, 20) called Student(CS2024) called Main Rahul hoon, age 20 Rahul padh raha hai (CGPA: 8.5)
EX 2.2

Object Class — Java Ka Root

Har class implicitly Object extend karti hai. Object ke methods: toString(), equals(), hashCode(), getClass() — sab ko override karna seekho.
import java.util.Objects;

class Book {
    String title;
    String author;
    double price;
    int    year;

    Book(String title, String author, double price, int year) {
        this.title  = title;
        this.author = author;
        this.price  = price;
        this.year   = year;
    }

    // ── Override Object.toString() ──
    // Bina override ke: Book@1b6d3586 (useless)
    // Override karne ke baad: readable output
    @Override
    public String toString() {
        return "Book{title='" + title + "', author='" + author
             + "', price=₹" + price + ", year=" + year + "}";
    }

    // ── Override Object.equals() ──
    // Bina override ke: reference compare (== jaisa)
    // Override karne ke baad: content compare
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;            // same reference
        if (!(obj instanceof Book)) return false; // type check
        Book other = (Book) obj;
        return Objects.equals(title, other.title)
            && Objects.equals(author, other.author)
            && price == other.price;
    }

    // ── Override hashCode() ──
    // equals() override karo to hashCode() bhi karo (contract)
    @Override
    public int hashCode() {
        return Objects.hash(title, author, price);
    }
}

public class ObjectClassDemo {
    public static void main(String[] args) {
        Book b1 = new Book("Java Programming", "James Gosling", 499.0, 2020);
        Book b2 = new Book("Java Programming", "James Gosling", 499.0, 2021);
        Book b3 = b1;  // same reference

        System.out.println("b1.toString():      " + b1);   // auto toString()
        System.out.println("b1.getClass():      " + b1.getClass().getSimpleName());
        System.out.println("b1.hashCode():      " + b1.hashCode());

        System.out.println("\nb1.equals(b2):      " + b1.equals(b2));  // content same
        System.out.println("b1.equals(b3):      " + b1.equals(b3));  // same ref
        System.out.println("b1 == b2:           " + (b1 == b2));     // ref compare
        System.out.println("b1 == b3:           " + (b1 == b3));     // same ref
    }
}
▶ Output
b1.toString(): Book{title='Java Programming', author='James Gosling', price=₹499.0, year=2020} b1.getClass(): Book b1.hashCode(): -1643507777 b1.equals(b2): true ← content same (year ignore kiya) b1.equals(b3): true ← same reference b1 == b2: false ← different objects b1 == b3: true ← same reference
03

super Keyword

super() Constructor · super.method() · super.field · 3 Uses Deep Dive

📖 Theory — super Kya Karta Hai?

super — Parent Ko Refer Karo Child Se

super keyword child class ke andar parent class ke members (fields, methods, constructor) ko access karne ke liye use hota hai. Ye 3 ways mein kaam karta hai:

Important: super() aur this() dono pehli line pe nahi aa sakte. Sirf ek hi allowed hai.

EX 3.1

super ke Teeno Uses — Ek Program Mein

super() constructor call, super.method() parent method access, super.field parent field access — teeno clearly dekho.
class Shape {
    String color;
    String type = "Generic Shape";  // parent field

    Shape(String color) {
        this.color = color;
        System.out.println("Shape constructor: color=" + color);
    }

    void draw() {
        System.out.println("Shape draw() — ek generic shape bana raha hai [" + color + "]");
    }

    double area() { return 0.0; }
}

class Circle extends Shape {
    double radius;
    String type = "Circle";  // child field — SAME NAME as parent (field hiding)

    Circle(String color, double radius) {
        // ── USE 1: super() — Parent constructor call ──
        // MUST be first line!
        super(color);
        this.radius = radius;
        System.out.println("Circle constructor: radius=" + radius);
    }

    @Override
    void draw() {
        // ── USE 2: super.method() — parent ki draw() bhi call karo ──
        super.draw();   // parent version
        System.out.println("Circle draw() — radius " + radius + " ka circle bana raha hai");
    }

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

    void showTypes() {
        // ── USE 3: super.field — parent field access ──
        System.out.println("this.type  (Circle's own): " + this.type);
        System.out.println("super.type (Shape's):      " + super.type);
    }
}

class Rectangle extends Shape {
    double width, height;

    Rectangle(String color, double width, double height) {
        super(color);   // super() constructor
        this.width  = width;
        this.height = height;
    }

    @Override
    void draw() {
        super.draw();
        System.out.println("Rectangle draw() — " + width + "×" + height);
    }

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

public class SuperKeyword {
    public static void main(String[] args) {
        System.out.println("=== Circle ===");
        Circle c = new Circle("Red", 7.5);
        c.draw();
        System.out.printf("Area: %.2f%n", c.area());
        c.showTypes();

        System.out.println("\n=== Rectangle ===");
        Rectangle r = new Rectangle("Blue", 5, 3);
        r.draw();
        System.out.printf("Area: %.2f%n", r.area());
    }
}
▶ Output
=== Circle === Shape constructor: color=Red Circle constructor: radius=7.5 Shape draw() — ek generic shape bana raha hai [Red] Circle draw() — radius 7.5 ka circle bana raha hai Area: 176.71 this.type (Circle's own): Circle super.type (Shape's): Generic Shape === Rectangle === Shape constructor: color=Blue Shape draw() — ek generic shape bana raha hai [Blue] Rectangle draw() — 5.0×3.0 Area: 15.00
EX 3.2

Bank Account System — super() Practical Use

BankAccount → SavingsAccount → FDAccount — real backend example. super() ka practical use, balance aur interest calculation.
class BankAccount {
    protected String accountNo;
    protected String holderName;
    protected double balance;

    BankAccount(String accountNo, String holderName, double initialBalance) {
        this.accountNo   = accountNo;
        this.holderName  = holderName;
        this.balance     = initialBalance;
    }

    void deposit(double amount) {
        if (amount > 0) { balance += amount; System.out.println("✅ Deposit: ₹" + amount); }
        else System.out.println("❌ Invalid deposit amount");
    }

    void withdraw(double amount) {
        if (amount > 0 && amount <= balance) { balance -= amount; System.out.println("✅ Withdraw: ₹" + amount); }
        else System.out.println("❌ Insufficient balance or invalid amount");
    }

    void showBalance() {
        System.out.printf("Account: %s | Holder: %s | Balance: ₹%.2f%n",
            accountNo, holderName, balance);
    }
}

class SavingsAccount extends BankAccount {
    private double interestRate;  // annual %
    private static final double MIN_BALANCE = 1000.0;

    SavingsAccount(String accountNo, String holderName,
                   double balance, double interestRate) {
        super(accountNo, holderName, balance);  // parent constructor
        this.interestRate = interestRate;
    }

    @Override
    void withdraw(double amount) {
        if (balance - amount < MIN_BALANCE) {
            System.out.println("❌ Min balance ₹" + MIN_BALANCE + " maintain karna zaroori hai");
        } else {
            super.withdraw(amount);   // parent ki withdraw logic use karo
        }
    }

    void addInterest() {
        double interest = balance * interestRate / 100;
        balance += interest;
        System.out.printf("💰 Interest added: ₹%.2f (%.1f%%)%n", interest, interestRate);
    }

    @Override
    void showBalance() {
        super.showBalance();  // parent ka display
        System.out.println("   Interest Rate: " + interestRate + "%");
    }
}

public class BankSystem {
    public static void main(String[] args) {
        SavingsAccount acc = new SavingsAccount("SB-1001", "Priya Sharma", 15000.0, 4.5);

        acc.showBalance();
        acc.deposit(5000);
        acc.withdraw(18000);   // Min balance check
        acc.withdraw(5000);    // Valid
        acc.addInterest();
        acc.showBalance();
    }
}
▶ Output
Account: SB-1001 | Holder: Priya Sharma | Balance: ₹15000.00 Interest Rate: 4.5% ✅ Deposit: ₹5000.0 ❌ Min balance ₹1000.0 maintain karna zaroori hai ✅ Withdraw: ₹5000.0 💰 Interest added: ₹675.00 (4.5%) Account: SB-1001 | Holder: Priya Sharma | Balance: ₹15675.00 Interest Rate: 4.5%
04

Method Overriding

@Override · Rules · Runtime Polymorphism · Covariant Return · Overriding vs Overloading

📖 Theory — Overriding Kya Hai?

Child Apne Tarike Se Kaam Kare — Override

Method Overriding tab hota hai jab child class parent class ke method ko same signature (same name, same parameters) ke saath redefine kare. Jab override kiya hua method call hota hai, child ka version run hota hai — parent ka nahi.

Ye Runtime Polymorphism ka base hai — ek Animal reference se Dog, Cat, Bird ke alag alag sounds sun sakte ho.

@Override annotation hamesha use karo — ye compile-time check deta hai ki tum actually kisi parent method ko override kar rahe ho, koi naya method nahi bana rahe.

RuleRequirementExample
Method nameSame hona chahiyeparent: eat() → child: eat()
ParametersSame (number + type)parent: eat(String) → child: eat(String)
Return typeSame OR covariant (subtype)parent: Animal getAnimal() → child: Dog getAnimal()
Access modifierSame OR more accessibleparent: protected → child: public ✅; parent: public → child: protected ❌
ExceptionSame or narrower checked exceptionsparent: IOException → child: FileNotFoundException ✅
static methodsOverride nahi hota — Method Hiding hota hai@Override nahi lagega static pe
private methodsOverride nahi ho saktaprivate methods invisible to child
final methodsOverride nahi ho saktafinal void eat() — cannot override

✅ Overriding

  • Same method name, same parameters
  • Child class redefines parent method
  • Runtime (Dynamic) Polymorphism
  • @Override annotation
  • Inheritance required

🔵 Overloading (alag hai!)

  • Same method name, DIFFERENT parameters
  • Same class mein bhi ho sakta hai
  • Compile-time (Static) Polymorphism
  • No @Override
  • Inheritance not required
EX 4.1

Animal Sound — Classic Override Example

Animal → Dog, Cat, Cow — har ek apna sound override karta hai. Runtime polymorphism dekho — Animal reference, different objects.
class Animal {
    String name;

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

    void makeSound() {
        System.out.println(name + ": .... (generic sound)");
    }

    void eat() {
        System.out.println(name + " khaana kha raha hai");
    }

    @Override
    public String toString() {
        return "Animal[" + name + "]";
    }
}

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

    @Override
    void makeSound() {
        System.out.println(name + ": Bhow Bhow! 🐕");
    }
    // eat() override nahi kiya — parent ka chalega
}

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

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

    @Override
    void eat() {
        System.out.println(name + " machhli khaana pasand karta hai 🐟");
    }
}

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

    @Override
    void makeSound() {
        System.out.println(name + ": Moo Moo! 🐄");
    }
}

public class MethodOverriding {
    public static void main(String[] args) {
        // ── Direct object calls ──
        Dog dog = new Dog("Bruno");
        Cat cat = new Cat("Whiskers");
        Cow cow = new Cow("Gauri");

        dog.makeSound();
        cat.makeSound();
        cow.makeSound();

        System.out.println();
        dog.eat();  // Animal ka (not overridden)
        cat.eat();  // Cat ka (overridden)

        System.out.println("\n=== Runtime Polymorphism — Animal reference ===");
        // Animal reference mein Dog/Cat/Cow — Runtime decide hoga
        Animal[] animals = {
            new Dog("Rex"),
            new Cat("Kitty"),
            new Cow("Nandini"),
            new Animal("Unknown")
        };

        for (Animal a : animals) {
            a.makeSound();  // Kaunsa version? JVM runtime pe decide karega!
        }
    }
}
▶ Output
Bruno: Bhow Bhow! 🐕 Whiskers: Meow Meow! 🐱 Gauri: Moo Moo! 🐄 Bruno khaana kha raha hai Whiskers machhli khaana pasand karta hai 🐟 === Runtime Polymorphism — Animal reference === Rex: Bhow Bhow! 🐕 Kitty: Meow Meow! 🐱 Nandini: Moo Moo! 🐄 Unknown: .... (generic sound)
EX 4.2

Employee Salary System — Override aur super.method()

Employee → Manager → Director — salary calculation override karo. Real backend payroll system jaisi structure.
class Employee {
    protected String name;
    protected double basicSalary;
    protected String department;

    Employee(String name, double basicSalary, String dept) {
        this.name = name; this.basicSalary = basicSalary; this.department = dept;
    }

    double calculateSalary() {
        double hra  = basicSalary * 0.4;   // 40% HRA
        double da   = basicSalary * 0.1;   // 10% DA
        return basicSalary + hra + da;
    }

    void printPayslip() {
        System.out.println("┌─────────────────────────────┐");
        System.out.printf( "│ Name:    %-20s│%n", name);
        System.out.printf( "│ Dept:    %-20s│%n", department);
        System.out.printf( "│ Basic:   ₹%-19.2f│%n", basicSalary);
        System.out.printf( "│ TOTAL:   ₹%-19.2f│%n", calculateSalary());
        System.out.println("└─────────────────────────────┘");
    }
}

class Manager extends Employee {
    private double bonus;

    Manager(String name, double basicSalary, String dept, double bonus) {
        super(name, basicSalary, dept);
        this.bonus = bonus;
    }

    @Override
    double calculateSalary() {
        return super.calculateSalary() + bonus;  // parent + bonus
    }

    @Override
    void printPayslip() {
        super.printPayslip();
        System.out.printf("  [Manager Bonus: ₹%.2f]%n", bonus);
    }
}

class Director extends Manager {
    private double stockOptions;

    Director(String name, double basicSalary, String dept, double bonus, double stocks) {
        super(name, basicSalary, dept, bonus);
        this.stockOptions = stocks;
    }

    @Override
    double calculateSalary() {
        return super.calculateSalary() + stockOptions;
    }
}

public class EmployeeSystem {
    public static void main(String[] args) {
        Employee[] staff = {
            new Employee("Rahul Kumar", 40000, "Engineering"),
            new Manager("Priya Sharma", 80000, "Engineering", 20000),
            new Director("Amit Verma", 150000, "C-Suite", 50000, 100000)
        };

        for (Employee e : staff) {
            e.printPayslip();
            System.out.printf("  → Net Salary: ₹%.2f%n%n", e.calculateSalary());
        }
    }
}
▶ Output
┌─────────────────────────────┐ │ Name: Rahul Kumar │ │ Dept: Engineering │ │ Basic: ₹40000.00 │ │ TOTAL: ₹60000.00 │ └─────────────────────────────┘ → Net Salary: ₹60000.00 ┌─────────────────────────────┐ │ Name: Priya Sharma │ │ Dept: Engineering │ │ Basic: ₹80000.00 │ │ TOTAL: ₹140000.00 │ └─────────────────────────────┘ [Manager Bonus: ₹20000.00] → Net Salary: ₹140000.00 ┌─────────────────────────────┐ │ Name: Amit Verma │ │ Dept: C-Suite │ │ Basic: ₹150000.00 │ │ TOTAL: ₹390000.00 │ └─────────────────────────────┘ → Net Salary: ₹390000.00
05

Types of Inheritance

Single · Multi-level · Hierarchical · Multiple (Interface se) · Hybrid

📖 5 Types — Java Mein Kya Kya Supported Hai

Inheritance ke Types

⚠️
Diamond Problem — Isliye Multiple Inheritance Nahi: Agar Cat Dog aur Animal dono extend kare, aur Dog aur Animal dono ka eat() method ho, to Cat ka eat() kaunsa version use kare? Ye ambiguity "Diamond Problem" hai. Java ne class-level multiple inheritance band karke ye problem avoid ki. Interface se multiple inheritance possible hai kyunki interface mein default implementation optional hai.
EX 5.1

Hierarchical Inheritance — School System

Person → Student, Teacher, Admin — ek parent, teen children. Har child apna extra behaviour add karta hai.
// ── PARENT ──────────────────────────────────────────
class Person {
    protected String name;
    protected int    age;
    protected String email;

    Person(String name, int age, String email) {
        this.name = name; this.age = age; this.email = email;
    }

    void introduce() {
        System.out.println("Hello! Main " + name + " hoon (Age: " + age + ")");
    }

    void login() { System.out.println(name + " ne login kiya: " + email); }
}

// ── CHILD 1: Student ────────────────────────────────
class Student extends Person {
    String rollNo;
    String course;
    double cgpa;

    Student(String name, int age, String email, String rollNo, String course, double cgpa) {
        super(name, age, email);
        this.rollNo = rollNo; this.course = course; this.cgpa = cgpa;
    }

    void submitAssignment(String subject) {
        System.out.println(name + " ne " + subject + " assignment submit ki 📝");
    }

    void viewResult() {
        System.out.printf("Roll: %s | Course: %s | CGPA: %.1f%n", rollNo, course, cgpa);
    }
}

// ── CHILD 2: Teacher ────────────────────────────────
class Teacher extends Person {
    String subject;
    int    yearsExp;
    double salary;

    Teacher(String name, int age, String email, String subject, int exp, double salary) {
        super(name, age, email);
        this.subject = subject; this.yearsExp = exp; this.salary = salary;
    }

    void takeClass(String topic) {
        System.out.println("Prof. " + name + " " + subject + " class le raha hai: " + topic + " 📚");
    }

    void assignHomework(String task) {
        System.out.println(name + " ne homework diya: " + task);
    }
}

// ── CHILD 3: Admin ──────────────────────────────────
class Admin extends Person {
    String role;
    int    accessLevel;

    Admin(String name, int age, String email, String role, int level) {
        super(name, age, email);
        this.role = role; this.accessLevel = level;
    }

    void manageUsers(String action) {
        System.out.println("[ADMIN] " + name + " (" + role + "): " + action + " 🔧");
    }
}

public class SchoolSystem {
    public static void main(String[] args) {
        Student s = new Student("Riya", 20, "riya@school.com", "CS2024", "B.Tech CS", 8.9);
        Teacher t = new Teacher("Dr. Gupta", 45, "gupta@school.com", "Java", 15, 80000);
        Admin   a = new Admin("Suresh", 35, "suresh@school.com", "SuperAdmin", 10);

        // Inherited methods
        s.introduce(); s.login(); s.submitAssignment("Java Arrays"); s.viewResult();
        System.out.println();
        t.introduce(); t.login(); t.takeClass("Inheritance"); t.assignHomework("Override 5 methods");
        System.out.println();
        a.introduce(); a.login(); a.manageUsers("New student account create kiya");
    }
}
▶ Output
Hello! Main Riya hoon (Age: 20) Riya ne login kiya: riya@school.com Riya ne Java Arrays assignment submit ki 📝 Roll: CS2024 | Course: B.Tech CS | CGPA: 8.9 Hello! Main Dr. Gupta hoon (Age: 45) Dr. Gupta ne login kiya: gupta@school.com Prof. Dr. Gupta Java class le raha hai: Inheritance 📚 Dr. Gupta ne homework diya: Override 5 methods Hello! Main Suresh hoon (Age: 35) Suresh ne login kiya: suresh@school.com [ADMIN] Suresh (SuperAdmin): New student account create kiya 🔧
06

final Keyword

final variable · final method · final class · Constants · Why Use final

📖 Theory — final Ka Matlab Hai "Band Kar Do"

final — 3 Jagah, 3 Meanings

final keyword 3 jagah lagta hai, aur teeno ke alag meanings hain:

EX 6.1

final — Variable, Method, Class

Teeno uses ek program mein — constants, non-overridable methods, non-extendable classes.
// ── final CLASS — extend nahi ho sakti ──
final class ImmutableConfig {
    final String DB_URL      = "jdbc:mysql://localhost/mydb";
    final int    PORT         = 8080;
    final String APP_NAME    = "MyJavaApp";

    void showConfig() {
        System.out.println("App:  " + APP_NAME);
        System.out.println("DB:   " + DB_URL);
        System.out.println("Port: " + PORT);
    }
}
// class ExtendedConfig extends ImmutableConfig {} // ❌ COMPILE ERROR

// ── Class with final METHODS ──
class Transaction {
    protected double amount;
    protected String txnId;

    static final double TAX_RATE = 0.18;  // static final = class-level constant

    Transaction(String txnId, double amount) {
        this.txnId = txnId; this.amount = amount;
    }

    // ── final METHOD — security critical, override nahi ho sakta ──
    final void applyGST() {
        double tax = amount * TAX_RATE;
        System.out.printf("TxnID: %s | Amount: ₹%.2f | GST(%.0f%%): ₹%.2f | Total: ₹%.2f%n",
            txnId, amount, TAX_RATE * 100, tax, amount + tax);
    }

    void process() {
        System.out.println("Processing transaction: " + txnId);
    }
}

class UPITransaction extends Transaction {
    String upiId;

    UPITransaction(String txnId, double amount, String upiId) {
        super(txnId, amount);
        this.upiId = upiId;
    }

    @Override
    void process() {
        System.out.println("UPI Payment to: " + upiId + " (₹" + amount + ")");
    }
    // applyGST() override karne ki koshish — COMPILE ERROR hoti
    // @Override void applyGST() {}  // ❌
}

public class FinalKeyword {
    public static void main(String[] args) {
        // final variable — local
        final int MAX = 100;
        // MAX = 200; // ❌ COMPILE ERROR — cannot assign to final variable
        System.out.println("MAX = " + MAX);

        ImmutableConfig cfg = new ImmutableConfig();
        cfg.showConfig();

        System.out.println("\nTAX_RATE (static final): " + Transaction.TAX_RATE);

        UPITransaction txn = new UPITransaction("TXN001", 2500.0, "user@paytm");
        txn.process();
        txn.applyGST();  // final method — parent ka hi chalega
    }
}
▶ Output
MAX = 100 App: MyJavaApp DB: jdbc:mysql://localhost/mydb Port: 8080 TAX_RATE (static final): 0.18 UPI Payment to: user@paytm (₹2500.0) TxnID: TXN001 | Amount: ₹2500.00 | GST(18%): ₹450.00 | Total: ₹2950.00
07

Abstract Classes

abstract keyword · Abstract Methods · Template Method Pattern · When to Use

📖 Theory — Abstract Class Kya Hai?

Adhuri Class — Jo Khud Object Nahi Ban Sakti

Abstract class woh class hai jo abstract keyword se declare hoti hai aur directly instantiate nahi ho sakti (new AbstractClass() invalid). Ye sirf inherit ki ja sakti hai.

Abstract class mein abstract methods ho sakte hain — jo sirf declare hote hain, define nahi. Child class ko ye methods implement karne mandatory hote hain.

Kab use karo: Jab ek common template chahiye ho aur kuch methods ka implementation child pe depend kare. Jaise "Shape" abstract hogi — area() har shape ke liye alag, but draw() common. Abstract class mein concrete methods bhi ho sakte hain.

✅ Abstract Class Use Karo

  • IS-A relationship strong ho
  • Common state (fields) share karni ho
  • Kuch methods ka default implementation ho
  • Constructor chahiye
  • Template Method Pattern banana ho

🔵 Interface Use Karo (next chapter)

  • Sirf capability/contract define karna ho
  • Multiple inheritance chahiye
  • No shared state (fields nahi)
  • Unrelated classes same capability share karein
EX 7.1

Shape Abstract Class — area() aur perimeter()

Abstract Shape class — area() aur perimeter() abstract. Circle, Rectangle, Triangle implement karte hain. Object nahi ban sakta Shape ka.
abstract class Shape {
    protected String color;
    private static int count = 0;

    Shape(String color) {
        this.color = color;
        count++;
    }

    // ── Abstract methods — child MUST implement ──
    abstract double area();
    abstract double perimeter();
    abstract String shapeName();

    // ── Concrete method — sab use kar sakte hain ──
    void displayInfo() {
        System.out.println("┌── " + shapeName() + " ──────────────────");
        System.out.printf( "│ Color:     %s%n", color);
        System.out.printf( "│ Area:      %.4f sq units%n", area());
        System.out.printf( "│ Perimeter: %.4f units%n", perimeter());
        System.out.println("└────────────────────────────");
    }

    static int getCount() { return count; }
}

class Circle extends Shape {
    private double radius;
    Circle(String color, double r) { super(color); this.radius = r; }

    @Override double area()      { return Math.PI * radius * radius; }
    @Override double perimeter() { return 2 * Math.PI * radius; }
    @Override String shapeName()  { return "Circle (r=" + radius + ")"; }
}

class Rectangle extends Shape {
    private double w, h;
    Rectangle(String color, double w, double h) { super(color); this.w=w; this.h=h; }

    @Override double area()      { return w * h; }
    @Override double perimeter() { return 2 * (w + h); }
    @Override String shapeName()  { return "Rectangle (" + w + "×" + h + ")"; }
}

class Triangle extends Shape {
    private double a, b, c;
    Triangle(String color, double a, double b, double c) {
        super(color); this.a=a; this.b=b; this.c=c;
    }

    @Override double perimeter() { return a + b + c; }
    @Override double area() {       // Heron's formula
        double s = perimeter() / 2;
        return Math.sqrt(s * (s-a) * (s-b) * (s-c));
    }
    @Override String shapeName() { return "Triangle ("+a+","+b+","+c+")"; }
}

public class AbstractClassDemo {
    public static void main(String[] args) {
        // Shape s = new Shape("Red"); // ❌ COMPILE ERROR — abstract class!

        Shape[] shapes = {
            new Circle("Red", 7),
            new Rectangle("Blue", 6, 4),
            new Triangle("Green", 3, 4, 5)
        };

        for (Shape s : shapes) {
            s.displayInfo();
        }

        System.out.println("Total shapes created: " + Shape.getCount());

        // Find largest area
        Shape largest = shapes[0];
        for (Shape s : shapes) if (s.area() > largest.area()) largest = s;
        System.out.println("Largest area: " + largest.shapeName());
    }
}
▶ Output
┌── Circle (r=7.0) ────────────────── │ Color: Red │ Area: 153.9380 sq units │ Perimeter: 43.9823 units └──────────────────────────── ┌── Rectangle (6.0×4.0) ────────────────── │ Color: Blue │ Area: 24.0000 sq units │ Perimeter: 20.0000 units └──────────────────────────── ┌── Triangle (3.0,4.0,5.0) ────────────────── │ Color: Green │ Area: 6.0000 sq units │ Perimeter: 12.0000 units └──────────────────────────── Total shapes created: 3 Largest area: Circle (r=7.0)
EX 7.2

Template Method Pattern — Abstract Class Ka Power

Algorithm ka skeleton parent mein, steps child mein. Report generation pattern — common structure, alag details.
abstract class ReportGenerator {

    // ── TEMPLATE METHOD — FINAL! Order fixed hai ──
    final void generateReport() {
        System.out.println("\n=== " + getReportTitle() + " ===");
        fetchData();          // child implement karega
        processData();        // child implement karega
        formatOutput();       // child implement karega
        printSummary();       // concrete — sab same
        System.out.println("Report generation complete ✅");
    }

    // ── Abstract steps — child MUST define ──
    abstract String getReportTitle();
    abstract void fetchData();
    abstract void processData();
    abstract void formatOutput();

    // ── Concrete step — same for all ──
    void printSummary() {
        System.out.println("[Generated: " + java.time.LocalDate.now() + "]");
    }
}

class SalesReport extends ReportGenerator {
    @Override String getReportTitle() { return "MONTHLY SALES REPORT"; }
    @Override void fetchData()    { System.out.println("📊 Sales DB se data fetch kiya"); }
    @Override void processData()  { System.out.println("📈 Revenue calculations done"); }
    @Override void formatOutput()  { System.out.println("📋 Table format mein print kiya"); }
}

class InventoryReport extends ReportGenerator {
    @Override String getReportTitle() { return "INVENTORY STATUS REPORT"; }
    @Override void fetchData()    { System.out.println("📦 Warehouse DB se stock data"); }
    @Override void processData()  { System.out.println("🔢 Low stock items flag kiye"); }
    @Override void formatOutput()  { System.out.println("📄 CSV format mein export kiya"); }
}

public class TemplatePattern {
    public static void main(String[] args) {
        ReportGenerator[] reports = { new SalesReport(), new InventoryReport() };
        for (ReportGenerator r : reports) r.generateReport();
    }
}
▶ Output
=== MONTHLY SALES REPORT === 📊 Sales DB se data fetch kiya 📈 Revenue calculations done 📋 Table format mein print kiya [Generated: 2025-07-15] Report generation complete ✅ === INVENTORY STATUS REPORT === 📦 Warehouse DB se stock data 🔢 Low stock items flag kiye 📄 CSV format mein export kiya [Generated: 2025-07-15] Report generation complete ✅
08

Java Interfaces

interface keyword · implements · Multiple Interface · default methods · Functional Interface

📖 Theory — Interface Kya Hai?

Pure Contract — Sirf "Kya Karna Hai", "Kaise" Nahi

Interface ek pure abstract type hai jo sirf contract define karta hai — kya methods implement karne hain. Kaise implement karein ye class pe depend karta hai.

Interface ke methods by default public abstract hote hain. Fields by default public static final — constants. Interface object nahi ban sakta.

Java 8+ mein: default methods (implementation with default), static methods interface mein allowed hain. Java 9+: private methods bhi.

Multiple Interface: Ek class multiple interfaces implement kar sakti hai — ye Java mein "multiple inheritance" ka safe solution hai!

FeatureAbstract ClassInterface
Instantiate❌ No❌ No
Multiple inherit❌ Single only✅ Multiple implements
Constructor✅ Yes❌ No
Instance fields✅ Yes❌ No (only static final)
Method typesabstract + concreteabstract + default + static
Access modifiersAnypublic only
Keywordextendsimplements
Use caseIS-A with shared stateCAN-DO / capability contract
EX 8.1

Interface Basics — Flyable, Swimmable, Runnable

Multiple interfaces implement karna — Duck fly bhi karta hai, swim bhi. Multiple inheritance safely.
// ── Interfaces — CAN-DO contracts ──
interface Flyable {
    int MAX_ALTITUDE = 10000;  // public static final (implicit)

    void fly();                // public abstract (implicit)
    void land();

    // Java 8+ default method — override optional
    default void glide() {
        System.out.println("Gliding at " + MAX_ALTITUDE/2 + " feet...");
    }
}

interface Swimmable {
    void swim();
    void dive();

    default void float_() {
        System.out.println("Floating on water surface 💧");
    }
}

interface Runnable {   // Note: different from java.lang.Runnable
    void run();
    void sprint();
}

// ── Duck: implements 2 interfaces ──
class Duck implements Flyable, Swimmable {
    String name;
    Duck(String name) { this.name = name; }

    @Override public void fly()  { System.out.println(name + " ud raha hai 🦆✈️"); }
    @Override public void land() { System.out.println(name + " utar raha hai"); }
    @Override public void swim() { System.out.println(name + " tair raha hai 🏊"); }
    @Override public void dive() { System.out.println(name + " gote laga raha hai 🤿"); }
}

// ── Eagle: implements 1 interface + Runnable ──
class Eagle implements Flyable, Runnable {
    String name;
    Eagle(String name) { this.name = name; }

    @Override public void fly()    { System.out.println(name + " bahut uuncha uda raha hai 🦅"); }
    @Override public void land()   { System.out.println(name + " shikaar pakad ke utra"); }
    @Override public void run()    { System.out.println(name + " daud raha hai 🏃"); }
    @Override public void sprint() { System.out.println(name + " bahut tez daud raha hai"); }

    @Override
    public void glide() {  // default method override kiya
        System.out.println(name + " eagle style mein glide kar raha hai 🦅");
    }
}

// ── Fish: only Swimmable ──
class Fish implements Swimmable {
    String name;
    Fish(String name) { this.name = name; }
    @Override public void swim() { System.out.println(name + " paani mein tair raha hai 🐟"); }
    @Override public void dive() { System.out.println(name + " gehraai mein gaya 🌊"); }
}

public class InterfaceDemo {
    public static void main(String[] args) {
        Duck duck   = new Duck("Donald");
        Eagle eagle = new Eagle("Sam");
        Fish fish   = new Fish("Nemo");

        System.out.println("=== Duck (Flyable + Swimmable) ===");
        duck.fly(); duck.swim(); duck.dive(); duck.glide(); // default method

        System.out.println("\n=== Eagle (Flyable + Runnable) ===");
        eagle.fly(); eagle.run(); eagle.glide(); // overridden default

        System.out.println("\n=== Fish (Swimmable only) ===");
        fish.swim(); fish.dive(); fish.float_(); // default method

        System.out.println("\n=== Interface reference use karo ===");
        Flyable[] fliers = { duck, eagle };
        for (Flyable f : fliers) f.fly();

        Swimmable[] swimmers = { duck, fish };
        for (Swimmable s : swimmers) s.swim();

        System.out.println("\nMAX_ALTITUDE constant: " + Flyable.MAX_ALTITUDE);
    }
}
▶ Output
=== Duck (Flyable + Swimmable) === Donald ud raha hai 🦆✈️ Donald tair raha hai 🏊 Donald gote laga raha hai 🤿 Gliding at 5000 feet... === Eagle (Flyable + Runnable) === Sam bahut uuncha uda raha hai 🦅 Sam daud raha hai 🏃 Sam eagle style mein glide kar raha hai 🦅 === Fish (Swimmable only) === Nemo paani mein tair raha hai 🐟 Nemo gehraai mein gaya 🌊 Floating on water surface 💧 === Interface reference use karo === Donald ud raha hai 🦆✈️ Sam bahut uuncha uda raha hai 🦅 Donald tair raha hai 🏊 Nemo paani mein tair raha hai 🐟 MAX_ALTITUDE constant: 10000
EX 8.2

Payment Gateway — Interface in Backend

PaymentProcessor interface — UPI, CreditCard, NetBanking implement karte hain. Real Spring Boot payment architecture jaisi.
// ── Interfaces ──────────────────────────────────────
interface PaymentProcessor {
    boolean processPayment(double amount, String recipient);
    boolean refund(String transactionId, double amount);
    String  getPaymentMode();

    default void printReceipt(double amount, boolean success) {
        System.out.printf("  [%s] %-10s ₹%.2f — %s%n",
            success ? "✅" : "❌", getPaymentMode(), amount,
            success ? "SUCCESS" : "FAILED");
    }
}

interface SecurePayment {
    boolean verifyOTP(String otp);
    void    generateOTP();
}

// ── UPI: implements both ─────────────────────────────
class UPIPayment implements PaymentProcessor, SecurePayment {
    private String upiId;
    UPIPayment(String upiId) { this.upiId = upiId; }

    @Override
    public boolean processPayment(double amount, String recipient) {
        System.out.println("  UPI: " + upiId + " → " + recipient);
        boolean ok = amount < 100000;
        printReceipt(amount, ok);  // default method
        return ok;
    }
    @Override
    public boolean refund(String txnId, double amount) {
        System.out.println("  UPI Refund: " + txnId + " → ₹" + amount);
        return true;
    }
    @Override public String  getPaymentMode() { return "UPI"; }
    @Override public void    generateOTP()     { System.out.println("  OTP sent to registered mobile"); }
    @Override public boolean verifyOTP(String otp) { return otp.equals("123456"); }
}

// ── Credit Card: only PaymentProcessor ──────────────
class CreditCardPayment implements PaymentProcessor {
    private String cardLast4;
    private double limit;
    CreditCardPayment(String last4, double limit) { this.cardLast4=last4; this.limit=limit; }

    @Override
    public boolean processPayment(double amount, String recipient) {
        System.out.println("  CC *" + cardLast4 + " → " + recipient);
        boolean ok = amount <= limit;
        printReceipt(amount, ok);
        if (ok) limit -= amount;
        return ok;
    }
    @Override
    public boolean refund(String txnId, double amount) {
        limit += amount; System.out.println("  CC Refund credited: ₹" + amount); return true;
    }
    @Override public String getPaymentMode() { return "CreditCard"; }
}

public class PaymentGateway {
    static void processOrder(PaymentProcessor processor, double amount, String to) {
        System.out.println("Processing ₹" + amount + " via " + processor.getPaymentMode());
        processor.processPayment(amount, to);
    }

    public static void main(String[] args) {
        UPIPayment         upi = new UPIPayment("user@okaxis");
        CreditCardPayment  cc  = new CreditCardPayment("4242", 50000);

        processOrder(upi, 2999.0, "Amazon");
        processOrder(cc,  15000.0, "Flipkart");

        System.out.println("\n--- UPI OTP Verification ---");
        upi.generateOTP();
        System.out.println("OTP Correct: " + upi.verifyOTP("123456"));

        System.out.println("\n--- Refunds ---");
        cc.refund("TXN999", 5000);
    }
}
▶ Output
Processing ₹2999.0 via UPI UPI: user@okaxis → Amazon [✅] UPI ₹2999.00 — SUCCESS Processing ₹15000.0 via CreditCard CC *4242 → Flipkart [✅] CreditCard ₹15000.00 — SUCCESS --- UPI OTP Verification --- OTP sent to registered mobile OTP Correct: true --- Refunds --- CC Refund credited: ₹5000.0
09

Runtime Polymorphism

Dynamic Dispatch · Upcasting · Downcasting · instanceof · Compile vs Runtime

📖 Theory — Polymorphism Deep Dive

Ek Reference, Multiple Forms

Polymorphism (Greek: poly = many, morph = forms) — ek cheez kai roopo mein kaam kare. Java mein 2 types:

Upcasting: Child object ko Parent reference mein store karna — automatic, always safe.
Downcasting: Parent reference ko Child reference mein convert karna — explicit cast zaroori, ClassCastException ka risk. instanceof check karo pehle.

EX 9.1

Dynamic Method Dispatch — Upcasting + Downcasting

Animal reference mein different animals — runtime decide hoga. Upcasting automatic, downcasting explicit with instanceof check.
class Animal {
    String name;
    Animal(String n) { name = n; }
    void makeSound() { System.out.println(name + ": generic sound"); }
    void eat()       { System.out.println(name + ": eating"); }
}

class Dog extends Animal {
    int tricks;
    Dog(String n, int t) { super(n); tricks = t; }
    @Override void makeSound() { System.out.println(name + ": Bhow Bhow! 🐕"); }
    void doTricks() { System.out.println(name + " jaanta hai " + tricks + " tricks!"); }
}

class Cat extends Animal {
    String breed;
    Cat(String n, String b) { super(n); breed = b; }
    @Override void makeSound() { System.out.println(name + ": Meow! 🐱"); }
    void purr() { System.out.println(name + "(" + breed + "): Purrrr..."); }
}

public class PolymorphismDemo {
    public static void main(String[] args) {

        // ── UPCASTING — automatic, always safe ──
        Animal a1 = new Dog("Bruno", 5);  // Dog → Animal reference
        Animal a2 = new Cat("Kitty", "Persian");
        Animal a3 = new Animal("Generic");

        System.out.println("=== Dynamic Dispatch ===");
        Animal[] animals = {a1, a2, a3};
        for (Animal a : animals) {
            a.makeSound();  // JVM decides at RUNTIME!
            a.eat();        // Animal ka method (not overridden)
        }

        System.out.println("\n=== DOWNCASTING with instanceof ===");
        for (Animal a : animals) {
            if (a instanceof Dog) {
                Dog d = (Dog) a;  // Safe downcasting
                d.doTricks();
            } else if (a instanceof Cat) {
                Cat c = (Cat) a;
                c.purr();
            } else {
                System.out.println(a.name + ": bas ek normal animal hai");
            }
        }

        System.out.println("\n=== Java 16+ Pattern Matching instanceof ===");
        for (Animal a : animals) {
            if (a instanceof Dog d) {        // Cast + variable ek line mein!
                System.out.println("Dog: " + d.tricks + " tricks");
            } else if (a instanceof Cat c) {
                System.out.println("Cat breed: " + c.breed);
            }
        }

        System.out.println("\n=== ClassCastException Example ===");
        try {
            Dog d = (Dog) a2;  // Cat ko Dog mein cast? RUNTIME EXCEPTION!
        } catch (ClassCastException e) {
            System.out.println("❌ ClassCastException: " + e.getMessage());
            System.out.println("✅ Hamesha instanceof check karo pehle!");
        }
    }
}
▶ Output
=== Dynamic Dispatch === Bruno: Bhow Bhow! 🐕 Bruno: eating Kitty: Meow! 🐱 Kitty: eating Generic: generic sound Generic: eating === DOWNCASTING with instanceof === Bruno jaanta hai 5 tricks! Kitty(Persian): Purrrr... Generic: bas ek normal animal hai === Java 16+ Pattern Matching instanceof === Dog: 5 tricks Cat breed: Persian === ClassCastException Example === ❌ ClassCastException: class Cat cannot be cast to class Dog ✅ Hamesha instanceof check karo pehle!
EX 9.2

Notification System — Polymorphism in Backend

SMS, Email, Push, WhatsApp — sab Notification. Ek method, multiple types handle. Real-world backend notification service.
abstract class Notification {
    protected String recipient;
    protected String message;
    private static   int    sentCount = 0;

    Notification(String recipient, String message) {
        this.recipient = recipient;
        this.message   = message;
    }

    abstract void send();
    abstract String getChannel();

    final void deliver() {
        System.out.printf("[%s] Sending to %s...%n", getChannel(), recipient);
        send();
        sentCount++;
        System.out.println("  Status: DELIVERED ✅%n");
    }

    static int getSentCount() { return sentCount; }
}

class SMSNotification extends Notification {
    SMSNotification(String phone, String msg) { super(phone, msg); }
    @Override void send()          { System.out.println("  📱 SMS: " + message.substring(0, Math.min(message.length(), 50))); }
    @Override String getChannel()  { return "SMS"; }
}

class EmailNotification extends Notification {
    String subject;
    EmailNotification(String email, String subj, String body) {
        super(email, body); this.subject = subj;
    }
    @Override void send()         { System.out.println("  📧 Email Subject: " + subject + "\n     Body: " + message); }
    @Override String getChannel() { return "EMAIL"; }
}

class PushNotification extends Notification {
    String deviceToken;
    PushNotification(String token, String msg) { super(token, msg); this.deviceToken = token; }
    @Override void send()         { System.out.println("  🔔 Push: " + message + " → device " + deviceToken.substring(0,8) + "..."); }
    @Override String getChannel() { return "PUSH"; }
}

// ── Notification Service — polymorphism ka fayda ──
class NotificationService {
    static void sendAll(Notification... notifications) {
        System.out.println("=== Sending " + notifications.length + " notifications ===");
        for (Notification n : notifications) n.deliver();  // polymorphism!
        System.out.println("Total sent: " + Notification.getSentCount());
    }
}

public class NotificationDemo {
    public static void main(String[] args) {
        NotificationService.sendAll(
            new SMSNotification("+91-9876543210", "Your OTP is 123456. Valid 5 mins."),
            new EmailNotification("user@gmail.com", "Order Confirmed!", "Your order #123 has been placed."),
            new PushNotification("abc123def456xyz789", "Sale starts in 1 hour! 🛍️")
        );
    }
}
▶ Output
=== Sending 3 notifications === [SMS] Sending to +91-9876543210... 📱 SMS: Your OTP is 123456. Valid 5 mins. Status: DELIVERED ✅ [EMAIL] Sending to user@gmail.com... 📧 Email Subject: Order Confirmed! Body: Your order #123 has been placed. Status: DELIVERED ✅ [PUSH] Sending to abc123def456xyz789... 🔔 Push: Sale starts in 1 hour! 🛍️ → device abc123de... Status: DELIVERED ✅ Total sent: 3
10

Practice Programs

Topic-wise Problems · Click to See Solution

🏗️

Set A — Basic Inheritance + super

extends, super(), super.method() — fundamentals solid karo

1
Phone → SmartPhone → GamingPhone Hierarchy 3 level hierarchy banao. Phone mein call(), text(). SmartPhone mein browsing(), apps(). GamingPhone mein fps(), overclockGPU().
Multi-levelsuper()
3 level inheritance — har level apni functionality add karta hai
class Phone {
    protected String brand; protected int storage;
    Phone(String brand, int storage) { this.brand=brand; this.storage=storage; }
    void call(String no) { System.out.println(brand + " calling: "+no+" 📞"); }
    void text(String msg) { System.out.println(brand + " SMS: "+msg.substring(0,Math.min(15,msg.length()))+"..."); }
}

class SmartPhone extends Phone {
    protected int ram;
    SmartPhone(String brand, int storage, int ram) { super(brand,storage); this.ram=ram; }
    void browse(String url) { System.out.println(brand + " browsing: "+url+" 🌐"); }
    void installApp(String app) { System.out.println(brand + " installing: "+app+" 📲"); }
}

class GamingPhone extends SmartPhone {
    private int gpuClock;
    GamingPhone(String brand, int storage, int ram, int gpu) {
        super(brand,storage,ram); this.gpuClock=gpu;
    }
    void playGame(String game) { System.out.println(brand+" playing "+game+" at 90fps 🎮"); }
    void overclockGPU() { System.out.println(brand+" GPU overclocked: "+gpuClock+"MHz → "+(gpuClock+200)+"MHz ⚡"); }
}

public class P1_PhoneHierarchy {
    public static void main(String[] args) {
        GamingPhone gp = new GamingPhone("ASUS ROG", 256, 16, 1200);
        gp.call("9876543210");      // Phone
        gp.browse("gaming.com");    // SmartPhone
        gp.installApp("PUBG");
        gp.playGame("BGMI");         // GamingPhone
        gp.overclockGPU();
        System.out.println("RAM: "+gp.ram+"GB | Storage: "+gp.storage+"GB");
    }
}
▶ Output
ASUS ROG calling: 9876543210 📞 ASUS ROG browsing: gaming.com 🌐 ASUS ROG installing: PUBG 📲 ASUS ROG playing BGMI at 90fps 🎮 ASUS ROG GPU overclocked: 1200MHz → 1400MHz ⚡ RAM: 16GB | Storage: 256GB
2
Library System — Book, EBook, AudioBook Book parent class banao. EBook mein fileSize, downloadable(). AudioBook mein duration, play(). toString() override karo.
Hierarchical@Override toString
Hierarchical — ek parent, do children. toString() override important hai.
class Book {
    protected String title, author;
    protected int pages; protected double price;

    Book(String title, String author, int pages, double price) {
        this.title=title; this.author=author; this.pages=pages; this.price=price;
    }
    void displayInfo() { System.out.println("📖 "+this); }
    @Override
    public String toString() {
        return "[Book] "+title+" by "+author+" | Pages: "+pages+" | ₹"+price;
    }
}

class EBook extends Book {
    private double fileSizeMB; private String format;

    EBook(String title, String author, int pages, double price, double mb, String fmt) {
        super(title,author,pages,price); fileSizeMB=mb; format=fmt;
    }
    void download() { System.out.println("📥 Downloading "+title+" ("+fileSizeMB+"MB "+format+")"); }
    @Override
    public String toString() {
        return "[EBook] "+title+" | "+fileSizeMB+"MB | Format: "+format+" | ₹"+price;
    }
}

class AudioBook extends Book {
    private int durationMins; private String narrator;

    AudioBook(String title, String author, int pages, double price, int mins, String narrator) {
        super(title,author,pages,price); durationMins=mins; this.narrator=narrator;
    }
    void play() { System.out.println("▶️  Playing: "+title+" (narrated by "+narrator+") - "+durationMins+" mins"); }
    @Override
    public String toString() {
        return "[AudioBook] "+title+" | Duration: "+durationMins+"mins | ₹"+price;
    }
}

public class P2_LibrarySystem {
    public static void main(String[] args) {
        Book[] library = {
            new Book("Java Basics", "James", 450, 499),
            new EBook("Clean Code", "Martin", 460, 699, 5.2, "PDF"),
            new AudioBook("Atomic Habits", "Clear", 320, 399, 345, "James Clear")
        };

        System.out.println("=== Library Catalog ===");
        for (Book b : library) b.displayInfo();

        System.out.println("\n=== Special Actions ===");
        for (Book b : library) {
            if (b instanceof EBook e)      e.download();
            if (b instanceof AudioBook ab) ab.play();
        }
    }
}
▶ Output
=== Library Catalog === 📖 [Book] Java Basics by James | Pages: 450 | ₹499.0 📖 [EBook] Clean Code | 5.2MB | Format: PDF | ₹699.0 📖 [AudioBook] Atomic Habits | Duration: 345mins | ₹399.0 === Special Actions === 📥 Downloading Clean Code (5.2MB PDF) ▶️ Playing: Atomic Habits (narrated by James Clear) - 345 mins
3
Abstract Animal — speak() abstract, eat() concrete Abstract Animal class banao speak() abstract se. Lion, Elephant, Parrot implement karo. Array mein rakho, loop mein call karo.
AbstractRuntime Polymorphism
Abstract class + polymorphism — classic pattern
abstract class Animal {
    protected String name; protected int weight;

    Animal(String name, int weight) { this.name=name; this.weight=weight; }

    abstract void speak();          // must implement
    abstract String getFood();     // must implement

    void eat() {
        System.out.println(name + " kha raha hai: " + getFood() + " 🍽️");
    }
    void info() {
        System.out.println("Animal: "+name+" | Weight: "+weight+"kg");
    }
}

class Lion extends Animal {
    Lion(String n) { super(n, 190); }
    @Override void speak()        { System.out.println(name + ": ROAARR!! 🦁"); }
    @Override String getFood()    { return "Meat"; }
}
class Elephant extends Animal {
    Elephant(String n) { super(n, 5000); }
    @Override void speak()        { System.out.println(name + ": Trumpetttt! 🐘"); }
    @Override String getFood()    { return "Sugarcane & Grass"; }
}
class Parrot extends Animal {
    private String catchPhrase;
    Parrot(String n, String phrase) { super(n, 1); catchPhrase = phrase; }
    @Override void speak()        { System.out.println(name + ": \"" + catchPhrase + "\" 🦜"); }
    @Override String getFood()    { return "Seeds & Fruits"; }
}

public class P3_AbstractAnimal {
    public static void main(String[] args) {
        Animal[] zoo = {
            new Lion("Simba"),
            new Elephant("Dumbo"),
            new Parrot("Mitthu", "Mitthu chahiye meetha!")
        };
        for (Animal a : zoo) { a.info(); a.speak(); a.eat(); System.out.println(); }
    }
}
▶ Output
Animal: Simba | Weight: 190kg Simba: ROAARR!! 🦁 Simba kha raha hai: Meat 🍽️ Animal: Dumbo | Weight: 5000kg Dumbo: Trumpetttt! 🐘 Dumbo kha raha hai: Sugarcane & Grass 🍽️ Animal: Mitthu | Weight: 1kg Mitthu: "Mitthu chahiye meetha!" 🦜 Mitthu kha raha hai: Seeds & Fruits 🍽️
4
Interface Printable + Saveable — Multiple Interface Printable interface (print(), preview()). Saveable interface (save(), getFilePath()). Document class dono implement kare. Report aur Image extend kare Document.
Multiple Interfaceimplements 2
Ek class dono interfaces implement karti hai — multiple capabilities
interface Printable {
    void print();
    default void preview() { System.out.println("📄 Preview: "+getTitle()+" [A4]"); }
    String getTitle();
}

interface Saveable {
    void save();
    String getFilePath();
    default void autoSave() { System.out.println("💾 AutoSave → "+getFilePath()); }
}

abstract class Document implements Printable, Saveable {
    protected String title; protected String author;
    Document(String t, String a) { title=t; author=a; }
    @Override public String getTitle() { return title; }
}

class Report extends Document {
    int pages;
    Report(String title, String author, int pages) { super(title,author); this.pages=pages; }
    @Override public void print()         { System.out.println("🖨️ Printing Report: "+title+" ("+pages+" pages)"); }
    @Override public void save()          { System.out.println("💾 Saving Report → "+getFilePath()); }
    @Override public String getFilePath() { return "/reports/"+title.replaceAll(" ","_")+".pdf"; }
}

class Image extends Document {
    int width, height;
    Image(String title, String author, int w, int h) { super(title,author); width=w; height=h; }
    @Override public void print()         { System.out.println("🖼️ Printing Image: "+title+" ("+width+"x"+height+")"); }
    @Override public void save()          { System.out.println("💾 Saving Image → "+getFilePath()); }
    @Override public String getFilePath() { return "/images/"+title+".png"; }
}

public class P4_MultiInterface {
    public static void main(String[] args) {
        Document[] docs = { new Report("Q3 Sales", "Finance", 24), new Image("logo", "Design", 1920, 1080) };
        for (Document d : docs) { d.preview(); d.print(); d.save(); d.autoSave(); System.out.println(); }
    }
}
▶ Output
📄 Preview: Q3 Sales [A4] 🖨️ Printing Report: Q3 Sales (24 pages) 💾 Saving Report → /reports/Q3_Sales.pdf 💾 AutoSave → /reports/Q3_Sales.pdf 📄 Preview: logo [A4] 🖼️ Printing Image: logo (1920x1080) 💾 Saving Image → /images/logo.png 💾 AutoSave → /images/logo.png
5
Hospital System — Doctor, Surgeon, Dentist Doctor parent banao (name, specialization, fees). Surgeon aur Dentist child. Surgeon mein performSurgery(), Dentist mein checkTeeth(). Polymorphism se sab doctors ki fees print karo.
HierarchicalPolymorphismReal World
Doctor → Surgeon, Dentist. Common treat() method override. Polymorphic array.
class Doctor {
    protected String name, specialization; protected double consultFee;
    Doctor(String n, String spec, double fee) { name=n; specialization=spec; consultFee=fee; }
    void treat(String patient) { System.out.println("Dr. "+name+" treating "+patient); }
    void prescribe(String med)  { System.out.println("  Rx: "+med); }
    void bill(String patient)  { System.out.printf("  Bill for %s: ₹%.0f%n", patient, consultFee); }
}

class Surgeon extends Doctor {
    private double surgeryFee;
    Surgeon(String n, double cf, double sf) { super(n,"Surgery",cf); surgeryFee=sf; }
    void performSurgery(String type) {
        System.out.println("🔪 Dr. "+name+" performing "+type+" surgery");
    }
    @Override
    void bill(String patient) {
        super.bill(patient);
        System.out.printf("  Surgery fee: ₹%.0f%n", surgeryFee);
    }
}

class Dentist extends Doctor {
    Dentist(String n, double fee) { super(n,"Dental",fee); }
    void checkTeeth() { System.out.println("🦷 Dr. "+name+" checking teeth & X-ray"); }
    @Override
    void treat(String patient) {
        super.treat(patient);
        System.out.println("  (Dental treatment)");
        checkTeeth();
    }
}

public class P5_HospitalSystem {
    public static void main(String[] args) {
        Doctor[] doctors = {
            new Doctor("Sharma", "General", 500),
            new Surgeon("Mehta", 1000, 50000),
            new Dentist("Gupta", 800)
        };
        System.out.println("=== Hospital Morning Rounds ===");
        for (Doctor d : doctors) {
            d.treat("Patient X");
            d.bill("Patient X");
            System.out.println();
        }
        // Surgery specific
        if (doctors[1] instanceof Surgeon s) s.performSurgery("Appendix");
    }
}
▶ Output
=== Hospital Morning Rounds === Dr. Sharma treating Patient X Bill for Patient X: ₹500 Dr. Mehta treating Patient X Bill for Patient X: ₹1000 Surgery fee: ₹50000 Dr. Gupta treating Patient X (Dental treatment) 🦷 Dr. Gupta checking teeth & X-ray Bill for Patient X: ₹800 🔪 Dr. Mehta performing Appendix surgery
🎮

Set B — Interface + Abstract Advanced

Real-world systems — Game, E-commerce, Ride app

6
Game Characters — Warrior, Mage, Archer Abstract GameCharacter banao — attack() abstract, takeDamage() concrete. Warrior, Mage, Archer extend karein. Array mein sab store karo, battle simulate karo.
AbstractPolymorphismFun Project
Abstract class + runtime polymorphism — game battle simulation
abstract class GameCharacter {
    protected String name; protected int hp; protected int maxHp; protected int level;

    GameCharacter(String n, int hp, int lvl) { name=n; this.hp=maxHp=hp; level=lvl; }

    abstract int attack();                          // returns damage
    abstract String getClass_();                    // character class name
    abstract void useSpecial();

    void takeDamage(int dmg) {
        hp = Math.max(0, hp - dmg);
        System.out.printf("  💔 %s took %d damage! HP: %d/%d%n", name, dmg, hp, maxHp);
        if (hp == 0) System.out.println("  ☠️  "+name+" is DEAD!");
    }
    boolean isAlive() { return hp > 0; }
    void status() { System.out.printf("[%s] %s Lv%d — HP: %d/%d%n",getClass_(),name,level,hp,maxHp); }
}

class Warrior extends GameCharacter {
    int str;
    Warrior(String n, int lvl) { super(n, 200, lvl); str=70; }
    @Override int  attack()     { System.out.println("⚔️  "+name+" swings sword!"); return str+lvl*5; }
    @Override String getClass_() { return "Warrior"; }
    @Override void useSpecial() { System.out.println("🛡️  "+name+" SHIELD BASH! Stun!"); }
}

class Mage extends GameCharacter {
    int mp = 100;
    Mage(String n, int lvl) { super(n, 100, lvl); }
    @Override int  attack()     { System.out.println("🔮 "+name+" casts FIREBALL!"); return 120+lvl*10; }
    @Override String getClass_() { return "Mage"; }
    @Override void useSpecial() { System.out.println("❄️  "+name+" BLIZZARD! Area freeze!"); }
}

class Archer extends GameCharacter {
    Archer(String n, int lvl) { super(n, 130, lvl); }
    @Override int  attack()     { System.out.println("🏹 "+name+" fires arrow!"); return 85+lvl*7; }
    @Override String getClass_() { return "Archer"; }
    @Override void useSpecial() { System.out.println("🎯 "+name+" RAPID SHOT! 3x arrows!"); }
}

public class P6_GameBattle {
    public static void main(String[] args) {
        GameCharacter[] heroes = {
            new Warrior("Thor", 5),
            new Mage("Gandalf", 10),
            new Archer("Legolas", 8)
        };
        GameCharacter boss = new Warrior("Dark Lord", 15);
        boss.hp = boss.maxHp = 500;

        System.out.println("=== BATTLE START ===");
        boss.status();
        for (GameCharacter hero : heroes) {
            hero.status();
            if (boss.isAlive()) {
                int dmg = hero.attack();
                boss.takeDamage(dmg);
                hero.useSpecial();
            }
        }
        System.out.println("\n=== FINAL STATUS ===");
        boss.status();
    }
}
▶ Output
=== BATTLE START === [Warrior] Dark Lord Lv15 — HP: 500/500 [Warrior] Thor Lv5 — HP: 200/200 ⚔️ Thor swings sword! 💔 Dark Lord took 95 damage! HP: 405/500 🛡️ Thor SHIELD BASH! Stun! [Mage] Gandalf Lv10 — HP: 100/100 🔮 Gandalf casts FIREBALL! 💔 Dark Lord took 220 damage! HP: 185/500 ❄️ Gandalf BLIZZARD! Area freeze! [Archer] Legolas Lv8 — HP: 130/130 🏹 Legolas fires arrow! 💔 Dark Lord took 141 damage! HP: 44/500 🎯 Legolas RAPID SHOT! 3x arrows! === FINAL STATUS === [Warrior] Dark Lord Lv15 — HP: 44/500
7
E-Commerce: Product → Electronics, Clothing, Food Abstract Product banao — calculateDiscount() abstract. Electronics mein warranty, Clothing mein size, Food mein expiryDate. Polymorphic cart banao.
AbstractE-CommerceBackend
Abstract class + polymorphic array = e-commerce cart simulation
abstract class Product {
    protected String name; protected double price; protected int qty;

    Product(String n, double p, int q) { name=n; price=p; qty=q; }

    abstract double calculateDiscount();
    abstract String getCategory();

    double finalPrice()  { return price - calculateDiscount(); }
    double lineTotal()   { return finalPrice() * qty; }

    void displayCartItem() {
        System.out.printf("  [%s] %-20s | ₹%.0f - ₹%.0f = ₹%.0f × %d = ₹%.0f%n",
            getCategory(), name, price, calculateDiscount(), finalPrice(), qty, lineTotal());
    }
}

class Electronics extends Product {
    int warrantyMonths;
    Electronics(String n, double p, int q, int w) { super(n,p,q); warrantyMonths=w; }
    @Override double calculateDiscount() { return price * 0.10; } // 10% off
    @Override String getCategory()        { return "ELEC"; }
}

class Clothing extends Product {
    String size;
    Clothing(String n, double p, int q, String size) { super(n,p,q); this.size=size; }
    @Override double calculateDiscount() { return price * 0.30; } // 30% off
    @Override String getCategory()        { return "CLOTH"; }
}

class FoodItem extends Product {
    String expiry;
    FoodItem(String n, double p, int q, String exp) { super(n,p,q); expiry=exp; }
    @Override double calculateDiscount() { return 0; }  // no discount on food
    @Override String getCategory()        { return "FOOD"; }
}

public class P7_ECommerceCart {
    public static void main(String[] args) {
        Product[] cart = {
            new Electronics("Laptop", 55000, 1, 24),
            new Clothing("T-Shirt", 999, 3, "M"),
            new FoodItem("Almonds 500g", 450, 2, "2025-12-01"),
            new Electronics("Headphones", 3500, 2, 12)
        };

        System.out.println("=== Shopping Cart ===");
        System.out.printf("  %-6s %-20s | %-7s %-7s %-7s %-4s %-8s%n",
            "Cat","Product","MRP","Disc","Final","Qty","Total");
        System.out.println("  "+"-".repeat(65));
        double grandTotal = 0;
        for (Product p : cart) { p.displayCartItem(); grandTotal += p.lineTotal(); }
        System.out.println("  "+"-".repeat(65));
        System.out.printf("  GRAND TOTAL: ₹%.0f%n", grandTotal);
    }
}
▶ Output
=== Shopping Cart === Cat Product | MRP Disc Final Qty Total ───────────────────────────────────────────────────────────────── [ELEC] Laptop | ₹55000 - ₹5500 = ₹49500 × 1 = ₹49500 [CLOTH] T-Shirt | ₹999 - ₹300 = ₹699 × 3 = ₹2097 [FOOD] Almonds 500g | ₹450 - ₹0 = ₹450 × 2 = ₹900 [ELEC] Headphones | ₹3500 - ₹350 = ₹3150 × 2 = ₹6300 ───────────────────────────────────────────────────────────────── GRAND TOTAL: ₹58797

⚠️ Common Mistakes in Inheritance

super() pehli line mein nahi: super(args) hamesha child constructor ki pehli line mein hona chahiye. Usse pehle kuch bhi nahi aa sakta. Error: "Constructor call must be the first statement in a constructor."
@Override annotation mat bhulo: Bina @Override ke agar method signature thoda bhi galat ho, Java naya method samajh lega, override nahi karega. Bug dhundhna mushkil ho jaata hai. Hamesha @Override lagao.
⚠️
Downcasting bina instanceof: Parent reference ko child mein cast karte waqt pehle instanceof check karo. Directly cast karne se ClassCastException runtime pe aata hai.
⚠️
Private fields accessible nahi: Child class parent ke private fields directly access nahi kar sakti. protected use karo ya getters/setters banao. Ye bahut common mistake hai.
IS-A vs HAS-A: "Dog IS-A Animal" → extends use karo. "Car HAS-A Engine" → Engine ko field banao (Composition). Ye distinction correct design ke liye sabse important hai.
💡
Abstract vs Interface — Quick Rule: Agar common state (fields) share karni ho ya IS-A relationship strong ho → Abstract class. Agar sirf capability contract chahiye ya multiple inheritance chahiye → Interface. Real-world mein dono use hote hain: abstract class + interface implementation ek saath.