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)
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.
Learning Outcomes — Bloom's Taxonomy Mapped
| Bloom's Level | Learning Outcome |
|---|---|
| 🔵 Remember | Define inheritance, list the types of inheritance supported in Java, and recall the syntax of the extends keyword |
| 🔵 Remember | State the 5 rules of method overriding and identify the 3 uses of the super keyword |
| 🔵 Understand | Explain why Java doesn't support multiple inheritance with classes (diamond problem) and how interfaces solve it |
| 🔵 Understand | Differentiate between compile-time polymorphism (overloading) and runtime polymorphism (overriding) with examples |
| 🟢 Apply | Implement a Shape class hierarchy with Circle, Rectangle, and Triangle using method overriding to calculate area |
| 🟢 Apply | Build a BankAccount hierarchy with SavingsAccount and CurrentAccount using super to invoke parent constructors |
| 🟢 Analyze | Trace the output of programs involving dynamic method dispatch and predict which overridden method executes at runtime |
| 🟢 Analyze | Compare access modifier rules in method overriding and identify compilation errors in given code |
| 🟠 Evaluate | Assess whether a given class design violates the Liskov Substitution Principle and suggest corrections |
| 🟠 Evaluate | Justify when to use final on a class vs. method vs. variable in a real-world banking application |
| 🟠 Create | Design a complete Payment Gateway system using abstract classes, inheritance, and polymorphic method dispatch |
| 🟠 Create | Create a Swing GUI application by extending JFrame, overriding paint(), and adding custom event handlers |
Concept Explanation — Inheritance & Polymorphism from Scratch
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!
| Type | Structure | Java Support | Example |
|---|---|---|---|
| Single | A → B | ✅ Yes | BankAccount → SavingsAccount |
| Multilevel | A → B → C | ✅ Yes | Account → SavingsAccount → SeniorCitizenAccount |
| Hierarchical | A → B, A → C | ✅ Yes | Shape → Circle, Shape → Rectangle |
| Multiple | A,B → C | ❌ No (classes) | Use interfaces instead |
| Hybrid | Mix of above | ❌ No (classes) | Use interfaces instead |
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
When child and parent have a variable with the same name, use super.variableName to access the parent's version.
When child overrides a parent method but still wants to call the parent's version: super.methodName().
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 Access | Child Can Be | Child Cannot Be |
|---|---|---|
public | public | protected, default, private |
protected | protected, public | default, private |
| default | default, protected, public | private |
private | Cannot 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()); } } }
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:
| Method | Default Behaviour | Why Override? |
|---|---|---|
toString() | Returns ClassName@hashcode | Return a meaningful string representation |
equals(Object) | Compares references (==) | Compare actual content/values |
hashCode() | Returns memory-based hash | Consistency with equals for HashMap/HashSet |
getClass() | Returns runtime class | Cannot override (final method) |
clone() | Shallow copy of object | Deep 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); } }
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.
| Feature | Compile-Time (Static) | Runtime (Dynamic) |
|---|---|---|
| Mechanism | Method Overloading | Method Overriding |
| Binding | Early binding (at compile time) | Late binding (at runtime) |
| Method Signature | Same name, different parameters | Same name, same parameters |
| Inheritance Required? | No — can be in same class | Yes — must be in parent-child |
| Performance | Slightly faster (resolved at compile) | Slightly slower (resolved at runtime) |
| Example | add(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! } } }
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
| Usage | Meaning | Example |
|---|---|---|
final variable | Value cannot be changed (constant) | final double PI = 3.14159; |
final method | Cannot be overridden by child class | final void validate() { } |
final class | Cannot 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(); } } }
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(); } }
Learn by Doing — 3-Tier Lab Structure
🟢 Tier 1 — GUIDED: Build BankAccount → SavingsAccount
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
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:
CurrentAccount: Overridewithdraw()to allow overdraft up to a limitFixedDepositAccount: Overridewithdraw()to block withdrawal before maturity- Use
instanceofto print account-type-specific details - Override
toString()in each child class
getAccountType() method using covariant return types — parent returns String, children return more specific strings.
🔴 Tier 3 — OPEN CHALLENGE: Complete Banking System
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.
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: Employee → Manager, 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: LibraryItem → Book, 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?
MCQ Assessment Bank — 30 Questions (Bloom's Mapped)
Remember / Identify (Q1–Q5)
Which keyword is used to inherit a class in Java?
- implements
- extends
- inherits
- super
extends keyword establishes an IS-A relationship between parent and child class.Which type of inheritance is NOT supported in Java with classes?
- Single
- Multilevel
- Multiple
- Hierarchical
The super keyword is used to:
- Access parent class members only
- Call parent constructor only
- Access parent variable, method, and constructor
- Create parent class objects
super has 3 uses: access parent variable (super.x), call parent method (super.method()), and call parent constructor (super(args)).Which annotation helps catch method overriding errors at compile time?
- @Overload
- @Override
- @Inherited
- @Polymorphic
Every class in Java is a child of which class?
- System
- Main
- Object
- Base
java.lang.Object, which provides toString(), equals(), hashCode(), etc.Understand / Explain (Q6–Q10)
Why does Java not support multiple inheritance with classes?
- Performance reasons
- Diamond problem — ambiguity in method resolution
- Memory limitations
- It was removed in Java 8
In method overriding, the access modifier of the child method:
- Must be the same as parent
- Can be more restrictive
- Cannot be more restrictive than the parent
- Must always be public
protected, child can be protected or public, but NOT private.What is dynamic method dispatch?
- Calling methods at compile time based on reference type
- The JVM decides which overridden method to call at runtime based on actual object type
- Using reflection to invoke methods
- Calling static methods through inheritance
What does final mean when applied to a method?
- The method runs last
- The method cannot be overridden by child classes
- The method is static
- The method returns a constant
final method cannot be overridden in any subclass. This is useful for security-critical methods like authentication.What is a covariant return type?
- Returning a parent class type when overriding
- Returning a subclass of the parent's return type when overriding
- Returning void in overridden methods
- Returning the same type in all methods
Animal, child returns Dog.Apply (Q11–Q15)
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?
- A
- B
- AB
- Compile error
show() is called despite the reference type being A.What is the output? class P { P() { print("P "); } } class Q extends P { Q() { print("Q "); } } and new Q();
- Q P
- P Q
- P
- Q
super() is implicitly called.Which line causes a compile error?
class Animal { public void eat() { } }
class Dog extends Animal {
@Override
protected void eat() { } // Line X
}
- No error
- Line X — more restrictive access
- Error in Animal class
- @Override is wrong
eat() is public, child tries protected which is more restrictive. Violates overriding rule #4.Given class A { int x = 5; } class B extends A { int x = 10; }. What does A obj = new B(); print(obj.x); output?
- 5
- 10
- 15
- Compile error
What does obj instanceof String return if obj is null?
- true
- false
- NullPointerException
- Compile error
instanceof returns false when the reference is null, never throws NullPointerException.Analyze (Q16–Q20)
In a Shape hierarchy, why is it better to declare area() as abstract in the parent rather than returning 0?
- Performance optimization
- Forces every child to provide its own implementation — prevents forgetting
- It uses less memory
- Java requires it
Why can't static methods be overridden?
- They are always final
- They belong to the class, not to objects — no dynamic dispatch
- Static methods can't access instance variables
- Java doesn't allow static in child classes
Compare: method overloading vs method overriding. Which statement is TRUE?
- Both require inheritance
- Overloading changes parameters; overriding keeps them the same
- Both are resolved at runtime
- Overriding can change the parameter list
What happens when you override equals() but NOT hashCode()?
- No impact
- Objects may not work correctly in HashSet and HashMap
- Compile error
- Runtime exception
a.equals(b) is true, then a.hashCode() == b.hashCode() must also be true. Breaking this causes bugs in hash-based collections.Which is true about constructor chaining in multilevel inheritance (A → B → C)?
- C's constructor runs first
- A's constructor runs first, then B's, then C's
- Only C's constructor runs
- Order is random
super() before its own body.Evaluate (Q21–Q25)
A team makes BankAccount a final class. Is this good design for a banking system?
- Yes — prevents tampering
- No — prevents creating SavingsAccount, CurrentAccount subclasses
- Depends on the database
- final doesn't affect inheritance
final prevents any specialization. A banking system needs SavingsAccount, CurrentAccount, etc. Better to make specific methods final instead.Which violates the Liskov Substitution Principle?
- Dog extends Animal and overrides eat() to eat differently
- Square extends Rectangle but setWidth() also changes height
- SavingsAccount extends BankAccount and adds calculateInterest()
- Circle extends Shape and overrides area()
Is it good practice to catch all exceptions using catch(Exception e) in overridden methods?
- Yes — handles everything
- No — too broad, hides specific errors, makes debugging harder
- Yes — improves performance
- It doesn't compile
Should toString() be overridden in every class?
- No — it's unnecessary overhead
- Yes — meaningful string representation aids debugging, logging, and display
- Only in final classes
- Only when using databases
toString() returns ClassName@hash which is useless. Overriding it makes debugging, logging, and unit testing much easier.Using protected access for parent class fields (like balance) is:
- Always bad — use private
- Good when child classes need direct access, but be aware it widens visibility to the package
- Same as public
- Same as private
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)
To design a notification system where Email, SMS, and Push notifications each send differently, you should:
- Use three unrelated classes
- Create an abstract Notification class with abstract send() and extend it
- Put all logic in one class with if-else
- Use static methods
send(). Polymorphism then allows processing any notification type uniformly.How would you design an immutable configuration class?
- Make all fields public
- Make the class final, all fields private final, no setters, set values in constructor
- Use protected fields
- Override equals() only
final class prevents extension, private final fields prevent modification, constructor sets all values, no setters. This is the immutable class pattern.To implement a Shape drawing application where new shapes can be added without modifying existing code, you should use:
- Switch-case with shape types
- Abstract Shape class with abstract draw() — new shapes just extend and override
- Static utility methods
- String-based shape names
You need a Swing GUI with a custom JFrame that draws shapes. The best approach is:
- Create a separate class and use JFrame as a field
- Extend JFrame, override paint(Graphics g), call super.paint(g) first
- Use only AWT, not Swing
- Override main() instead
paint() is the standard way to create custom Swing frames. Always call super.paint(g) first to clear the canvas.To create a banking system that supports future account types without changing existing code, you should:
- Use a single class with type flags
- Define abstract BankAccount with abstract methods, add new types by extending
- Use arrays of primitives
- Avoid inheritance entirely
calculateInterest(), withdraw(). New account types extend and provide their implementation. Existing code using BankAccount references works without modification.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.
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.
Lab Programs — Lab 7 & Lab 8
🔬 Lab 7 — Inheritance Using Swing: JFrame → CustomFrame
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.
🔬 Lab 8 — Polymorphism with Access Control
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"); } } } }
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.
ContractEmployee with hourly rate. Override calculatePay() to compute hourly × hours worked. Add a method isEligibleForPF() that uses instanceof to check if employee qualifies.
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).
| Detail | Info |
|---|---|
| Tools Used Daily | Java, 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 Hiring | Samsung R&D, Google, Microsoft, Amazon, Flipkart, Paytm, PhonePe, Adobe, Uber, Ola |
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
| Platform | Best For | Typical Rate |
|---|---|---|
| Internshala | Indian student Java projects | ₹5,000–₹15,000/project |
| Fiverr | Global clients, Java desktop apps | $25–$100/gig (₹2K–₹8K) |
| Upwork | Longer Java projects | $15–$50/hour |
| Local Businesses | Shops, 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)
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 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
Earning Checkpoint — Unit 8 Readiness
| Skill Learned | Tool / Technique | Portfolio Evidence | Earn-Ready? |
|---|---|---|---|
| Inheritance Hierarchy | Java extends | BankAccount → SavingsAccount/CurrentAccount | ✅ Yes — core OOP skill |
| Method Overriding | @Override annotation | Shape hierarchy with area() polymorphism | ✅ Yes — interview essential |
| Dynamic Dispatch | Parent ref + child object | PaymentGateway polymorphic demo | ✅ Yes — used in all Java frameworks |
| Swing GUI (Lab 7) | JFrame extension | CustomFrame with paint() override | ✅ Yes — desktop app foundation |
| Access Control (Lab 8) | Access modifiers in overriding | PayrollSystem with Employee hierarchy | ✅ Yes — real-world design pattern |
| Object class methods | toString, equals, hashCode | Student class with proper overrides | ✅ Yes — asked in 90% of interviews |
| final keyword | final class/method/variable | ImmutableConfig example | ✅ Yes — security-critical code |
✅ Unit 8 complete. MCQs: 30. Labs 7,8 covered. Ready for Unit 9!
[QR: Link to EduArtha video tutorial — Java Inheritance & Polymorphism]