Object Oriented Programming With JavaUnit 412 min read
Inheritance & Method Overriding: Types, Rules & Real-World Use
Unit 4 of Object Oriented Programming With Java covers inheritance (single, multilevel, hierarchical, multiple via interfaces), method overriding (runtime polymorphism), constructor chaining, and Java’s restrictions on multiple inheritance. It explains how to reuse code, enforce design rules, and implement dynamic meth
Core Concepts
1. Inheritance: Code Reusability & Hierarchy
Inheritance allows a subclass (child) to inherit fields and methods from a superclass (parent). Java supports four types:
Types of Inheritance in Java:
| Type | Definition | Example |
|---|---|---|
| Single | One subclass inherits from one superclass. | Animal → Dog |
| Multilevel | Chain of inheritance (grandparent → parent → child). | Vehicle → Car → SportsCar |
| Hierarchical | Multiple subclasses inherit from one superclass. | Shape → Circle, Shape → Rectangle |
| Multiple | Not directly supported (Java prohibits it). Solved via interfaces. | Interface A + B → Class C (implements both) |
Why Java Bans Multiple Inheritance for Classes?
- Diamond Problem: Ambiguity when two superclasses define the same method.
class A { void show() {} } class B extends A { void show() {} } // Error if C extends both A and B - Solution: Use interfaces (multiple interfaces can be implemented).
2. Constructor Chaining in Inheritance
When a subclass object is created, constructors execute in this order:
- Superclass constructor (top to bottom).
- Subclass constructor.
class Parent {
Parent() { System.out.println("Parent constructor"); }
}
class Child extends Parent {
Child() { System.out.println("Child constructor"); }
}
public class Main {
public static void main(String[] args) {
Child c = new Child();
}
}
Output:
Parent constructor
Child constructor
Trace Table:
| Step | Action | State After Step |
|---|---|---|
| 1 | new Child() called |
Parent constructor executes |
| 2 | Parent constructor finishes | Child constructor executes |
| 3 | Child constructor finishes | Object c fully initialized |
3. Method Overriding: Runtime Polymorphism
Overriding occurs when a subclass provides a specific implementation of a method already defined in its superclass. Key rules:
- Signature must match exactly (same name, parameters, return type).
- Access modifier cannot be more restrictive (e.g.,
protected→privateis invalid). @Overrideannotation (optional but recommended) ensures correctness.
Example: Shape Hierarchy
class Shape {
void draw() { System.out.println("Drawing a shape"); }
}
class Circle extends Shape {
@Override
void draw() { System.out.println("Drawing a circle"); }
}
Trace:
Real-World Analogy:
- Nepal’s NTC (National Transport Commission) defines a
Vehicleclass with acalculateTax()method.- A
Carsubclass overrides it to apply a different tax formula thanBike. - At runtime, NTC’s system calls the correct subclass method based on the vehicle type.
- A
4. final Keyword: Restricting Inheritance
| Use Case | Syntax Example | Purpose |
|---|---|---|
| Final Class | final class SealedClass |
Prevents inheritance (e.g., String, Integer). |
| Final Method | final void method() |
Prevents overriding (e.g., Object.hashCode()). |
| Final Variable | final int MAX_SIZE = 100; |
Constant value (immutable after initialization). |
Why Use final?
- Security: Prevent tampering (e.g.,
Math.PI). - Performance: Optimizes JVM (no runtime method lookup for
finalmethods). - Design: Enforces immutability (e.g.,
Stringthreadsafety).
5. Dynamic Method Dispatch
Java uses runtime polymorphism to determine which overridden method to call. The JVM resolves the method at runtime based on the object’s actual type (not reference type).
Example: Bank Loans
class Loan {
void calculateInterest() { System.out.println("Default interest"); }
}
class HomeLoan extends Loan {
@Override
void calculateInterest() { System.out.println("5% home loan interest"); }
}
class CarLoan extends Loan {
@Override
void calculateInterest() { System.out.println("8% car loan interest"); }
}
public class Main {
public static void main(String[] args) {
Loan loan1 = new HomeLoan();
Loan loan2 = new CarLoan();
loan1.calculateInterest(); // Output: 5%
loan2.calculateInterest(); // Output: 8%
}
}
Trace Table:
| Object Reference | Actual Object Type | Method Called | Output |
|---|---|---|---|
loan1 |
HomeLoan |
HomeLoan.calculateInterest() |
"5% home loan interest" |
loan2 |
CarLoan |
CarLoan.calculateInterest() |
"8% car loan interest" |
In the Real World
eSewa (Nepal):
- Uses inheritance for payment methods. The base
Paymentclass definesprocess(), while subclasses likeKhaltiPaymentandEbsePaymentoverride it with their own APIs. - Dynamic dispatch ensures the correct payment gateway is called at runtime.
- Uses inheritance for payment methods. The base
Pathao (Ride-Hailing):
- Hierarchical inheritance:
Vehicle(superclass) →Car,Bike,Auto(subclasses). - Each subclass overrides
calculateFare()to apply different pricing logic (e.g., distance-based for cars, time-based for autos).
- Hierarchical inheritance:
Nepal Stock Exchange (NEPSE):
- Abstract classes model
Stock(with abstractcalculateDividend()), whileBlueChipStockandGrowthStockprovide concrete implementations. - Interfaces like
Tradeable(withbuy(),sell()) are implemented by all stock types.
- Abstract classes model
Worked Example: College Ranking System
Problem:
Design a system where a College class tracks cname and rank. A University subclass adds totalStudents and overrides showRecord() to include university-specific details.
class College {
String cname;
int crank;
void setCollege(String name, int rank) {
cname = name; crank = rank;
}
void showRecord() {
System.out.println("College: " + cname + ", Rank: " + crank);
}
}
class University extends College {
int totalStudents;
void setUniversity(String name, int rank, int students) {
setCollege(name, rank); // Reuses superclass method
totalStudents = students;
}
@Override
void showRecord() {
super.showRecord(); // Calls superclass method
System.out.println("Students: " + totalStudents);
}
}
public class Main {
public static void main(String[] args) {
University triChandra = new University();
triChandra.setUniversity("Tribhuvan University", 1, 50000);
triChandra.showRecord();
}
}
Output:
College: Tribhuvan University, Rank: 1
Students: 50000
State After Each Step:
sequenceDiagram
participant UC as University
participant C as College
UC->>C: setCollege("TU", 1)
C-->>UC: cname="TU", crank=1
UC->>UC: totalStudents=50000
UC->>C: showRecord()
C-->>UC: "College: TU, Rank: 1"
UC->>UC: "Students: 50000"Comparison: Inheritance vs. Interfaces
| Feature | Inheritance (Class) | Interface |
|---|---|---|
| Keyword | extends |
implements |
| Methods | Can have concrete + abstract | Only abstract (default since Java 8) |
| Variables | Can have instance variables | Only public static final (constants) |
| Multiple Support | No (diamond problem) | Yes (a class can implement many) |
| Use Case | "Is-a" relationship (e.g., Dog is an Animal) |
"Can-do" relationship (e.g., Flyable interface) |
Example: Multiple Inheritance via Interfaces
interface Flyable { void fly(); }
interface Swimmable { void swim(); }
class Duck implements Flyable, Swimmable {
public void fly() { System.out.println("Flying"); }
public void swim() { System.out.println("Swimming"); }
}
Exam Tip
Diagrams > Text: Always draw UML class diagrams for inheritance hierarchies. Label:
+for public methods,#for protected,-for private.- Use solid arrows (
--|>) for inheritance, dashed (..|>) for interfaces.
Constructor Chaining: Expect questions on the order of execution. Memorize:
- Superclass constructors run before subclass constructors.
- Use
super()to explicitly call a superclass constructor (default if omitted).
Method Overriding Pitfalls:
- Return type: Covariant return types (e.g.,
Number→Integer) are allowed in Java 5+. @Override: Always use it to catch errors (e.g., typo in method name).
- Return type: Covariant return types (e.g.,
finalKeyword:- Class: "Cannot be inherited" (e.g.,
String). - Method: "Cannot be overridden" (e.g.,
Object.hashCode()). - Variable: "Cannot be reassigned" (e.g.,
final int MAX = 100;).
- Class: "Cannot be inherited" (e.g.,
Dynamic Dispatch:
- The reference type determines which method is accessible, but the actual object type determines which is called.
- Example:
Shape s = new Circle();→s.draw()callsCircle.draw().
Common Exam Questions:
- "Why can’t Java support multiple inheritance for classes?" → Diamond problem.
- "How does constructor chaining work?" → Trace the order with a diagram.
- "Differentiate between overloading and overriding."
Feature Overloading Overriding Method Signature Same name, different parameters Same name, same parameters Return Type Can vary Must match (covariant allowed) Polymorphism Compile-time Runtime
Practice Questions (Self-Check)
Code Trace: Given the following, what is the output?
class A { A() { System.out.print("A"); } } class B extends A { B() { System.out.print("B"); } } public class Main { public static void main(String[] args) { new B(); } }Answer:
AB(Constructor chaining:A→B).Design: Create a
Vehicleclass withstart()and aCarsubclass that overrides it to print"Car started with key". Usesuperto call the parent method.Short Answer:
- What is the output of
System.out.println(new Circle().toString())ifCircleextendsShapeand overridestoString()? - Why is
Stringdeclared asfinalin Java?
- What is the output of
Based on the TU BITM syllabus for Object Oriented Programming With Java (IT234), unit 4.
Discussion
Loading…