Java Programming
Lecture 10: Inheritance and Method Overriding
Course: 4343203 - Java Programming
GTU Semester 4 | Unit 2
Learning Objectives:
- Master inheritance concepts and implementation
- Understand method overriding and polymorphism
- Learn super keyword usage and constructor chaining
- Apply inheritance hierarchies in real applications
- Handle inheritance-related design patterns
Understanding Inheritance
Inheritance is a mechanism where a new class (subclass/child) acquires the properties and methods of an existing class (superclass/parent), promoting code reusability and establishing an "is-a" relationship.
Key Inheritance Concepts:
- Superclass/Parent: The class being inherited from
- Subclass/Child: The class that inherits
- extends keyword: Used to establish inheritance
- Is-a relationship: Subclass is a type of superclass
- Code reusability: Inherit existing functionality
Benefits of Inheritance:
- Code reusability and reduced redundancy
- Easier maintenance and updates
- Polymorphism support
- Real-world modeling
- Extensibility for future enhancements
Basic Inheritance Syntax:
// Superclass (Parent)
public class Vehicle {
protected String brand;
protected int year;
protected String color;
public Vehicle(String brand, int year, String color) {
this.brand = brand;
this.year = year;
this.color = color;
}
public void start() {
System.out.println("Vehicle is starting...");
}
public void stop() {
System.out.println("Vehicle is stopping...");
}
}
// Subclass (Child)
public class Car extends Vehicle {
private int doors;
private String fuelType;
public Car(String brand, int year, String color,
int doors, String fuelType) {
super(brand, year, color); // Call parent constructor
this.doors = doors;
this.fuelType = fuelType;
}
public void honk() {
System.out.println("Car is honking: Beep beep!");
}
}Types of Inheritance
Single Inheritance:
One subclass inherits from one superclass.
// Single Inheritance Example
class Animal {
String name;
public void eat() {
System.out.println(name + " is eating");
}
}
class Dog extends Animal {
public void bark() {
System.out.println(name + " is barking");
}
}
// Usage:
Dog dog = new Dog();
dog.name = "Buddy";
dog.eat(); // Inherited method
dog.bark(); // Own methodMultilevel Inheritance:
A chain of inheritance where each class extends another.
// Multilevel Inheritance Example
class Animal {
public void breathe() {
System.out.println("Animal is breathing");
}
}
class Mammal extends Animal {
public void giveBirth() {
System.out.println("Mammal gives birth");
}
}
class Dog extends Mammal {
public void bark() {
System.out.println("Dog is barking");
}
}
// Dog inherits from both Mammal and Animal
Dog dog = new Dog();
dog.breathe(); // From Animal
dog.giveBirth(); // From Mammal
dog.bark(); // Own methodHierarchical Inheritance:
Multiple subclasses inherit from one superclass.
// Hierarchical Inheritance Example
class Shape {
protected String color;
public Shape(String color) {
this.color = color;
}
public void draw() {
System.out.println("Drawing a " + color + " shape");
}
}
class Circle extends Shape {
private double radius;
public Circle(String color, double radius) {
super(color);
this.radius = radius;
}
public double getArea() {
return Math.PI * radius * radius;
}
}
class Rectangle extends Shape {
private double width, height;
public Rectangle(String color, double width, double height) {
super(color);
this.width = width;
this.height = height;
}
public double getArea() {
return width * height;
}
}Note: Java does NOT support multiple inheritance of classes (one class extending multiple classes) to avoid the Diamond Problem. However, it supports multiple inheritance of interfaces.
Method Overriding
What is Method Overriding?
Method overriding allows a subclass to provide a specific implementation of a method that is already defined in its superclass.
Overriding Rules:
- Method signature must be identical
- Return type must be same or covariant
- Access modifier cannot be more restrictive
- Cannot override static, final, or private methods
- Use @Override annotation for clarity
Basic Overriding Example:
class Animal {
public void makeSound() {
System.out.println("Animal makes a sound");
}
public void move() {
System.out.println("Animal moves");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Dog barks: Woof!");
}
@Override
public void move() {
System.out.println("Dog runs on four legs");
}
}Runtime Polymorphism:
public class PolymorphismDemo {
public static void main(String[] args) {
// Reference variable of parent type
Animal animal1 = new Animal();
Animal animal2 = new Dog(); // Polymorphism
Animal animal3 = new Cat(); // Polymorphism
// Method calls resolved at runtime
animal1.makeSound(); // "Animal makes a sound"
animal2.makeSound(); // "Dog barks: Woof!"
animal3.makeSound(); // "Cat meows: Meow!"
// Array of different animal types
Animal[] zoo = {
new Dog(),
new Cat(),
new Bird(),
new Fish()
};
System.out.println("Zoo sounds:");
for (Animal animal : zoo) {
animal.makeSound(); // Different sound for each
}
}
}
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Cat meows: Meow!");
}
}
class Bird extends Animal {
@Override
public void makeSound() {
System.out.println("Bird chirps: Tweet!");
}
}The super Keyword
Uses of super Keyword:
- Access parent's variables
- Call parent's methods
- Call parent's constructors
1. Accessing Parent Variables:
class Parent {
protected String name = "Parent";
}
class Child extends Parent {
private String name = "Child";
public void displayNames() {
System.out.println("Child name: " + this.name);
System.out.println("Parent name: " + super.name);
}
}2. Calling Parent Methods:
class Vehicle {
public void start() {
System.out.println("Vehicle engine starting...");
}
}
class Car extends Vehicle {
@Override
public void start() {
super.start(); // Call parent method first
System.out.println("Car engine started successfully!");
}
}3. Constructor Chaining with super:
class Employee {
protected String name;
protected int id;
protected double salary;
public Employee(String name, int id) {
this.name = name;
this.id = id;
this.salary = 30000.0; // Default salary
System.out.println("Employee constructor called");
}
public Employee(String name, int id, double salary) {
this.name = name;
this.id = id;
this.salary = salary;
System.out.println("Employee parameterized constructor");
}
}
class Manager extends Employee {
private String department;
private double bonus;
public Manager(String name, int id, String department) {
super(name, id); // Call parent constructor
this.department = department;
this.bonus = 5000.0;
System.out.println("Manager constructor called");
}
public Manager(String name, int id, double salary,
String department, double bonus) {
super(name, id, salary); // Call specific parent constructor
this.department = department;
this.bonus = bonus;
System.out.println("Manager full constructor called");
}
public double getTotalSalary() {
return salary + bonus; // Access protected variable
}
}Important: super() must be the first statement in a constructor. If not explicitly called, Java automatically inserts super() to call the parent's default constructor.
Access Modifiers and Inheritance
Access Modifier Visibility:
| Modifier | Same Class | Same Package | Subclass | Different Package |
|---|---|---|---|---|
| private | ✅ | ❌ | ❌ | ❌ |
| default | ✅ | ✅ | ❌* | ❌ |
| protected | ✅ | ✅ | ✅ | ❌ |
| public | ✅ | ✅ | ✅ | ✅ |
*Only if subclass is in same package
Overriding Access Rules:
- Cannot reduce visibility when overriding
- Can increase visibility
- protected → public ✅
- public → protected ❌
- private methods cannot be overridden
Access Modifier Examples:
public class Parent {
private int privateVar = 10; // Not inherited
int defaultVar = 20; // Package visibility
protected int protectedVar = 30; // Inherited
public int publicVar = 40; // Inherited
private void privateMethod() {
System.out.println("Private method");
}
protected void protectedMethod() {
System.out.println("Protected method");
}
public void publicMethod() {
System.out.println("Public method");
}
}
public class Child extends Parent {
public void accessParentMembers() {
// System.out.println(privateVar); // ❌ Error!
System.out.println(defaultVar); // ✅ If same package
System.out.println(protectedVar); // ✅ Always accessible
System.out.println(publicVar); // ✅ Always accessible
// privateMethod(); // ❌ Error!
protectedMethod(); // ✅ Accessible
publicMethod(); // ✅ Accessible
}
// Method overriding with access modifier changes
@Override
public void protectedMethod() { // Increased visibility: protected → public
super.protectedMethod();
System.out.println("Child's enhanced protected method");
}
}Real-world Inheritance Example
Banking System Hierarchy:
// Base Account class
public abstract class Account {
protected String accountNumber;
protected String holderName;
protected double balance;
protected String accountType;
public Account(String accountNumber, String holderName,
String accountType) {
this.accountNumber = accountNumber;
this.holderName = holderName;
this.accountType = accountType;
this.balance = 0.0;
}
// Common methods for all accounts
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("Deposited: $" + amount);
}
}
public boolean withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println("Withdrawn: $" + amount);
return true;
}
return false;
}
// Abstract method - must be implemented by subclasses
public abstract double calculateInterest();
public void displayInfo() {
System.out.println("Account: " + accountNumber);
System.out.println("Holder: " + holderName);
System.out.println("Type: " + accountType);
System.out.println("Balance: $" + balance);
}
// Getters
public String getAccountNumber() { return accountNumber; }
public double getBalance() { return balance; }
}Specialized Account Types:
// Savings Account
public class SavingsAccount extends Account {
private double interestRate;
private int minBalance;
public SavingsAccount(String accountNumber, String holderName,
double interestRate) {
super(accountNumber, holderName, "Savings");
this.interestRate = interestRate;
this.minBalance = 1000;
}
@Override
public boolean withdraw(double amount) {
if (balance - amount >= minBalance) {
return super.withdraw(amount);
}
System.out.println("Insufficient balance! Minimum balance: $" + minBalance);
return false;
}
@Override
public double calculateInterest() {
return balance * interestRate / 100;
}
public void applyInterest() {
double interest = calculateInterest();
balance += interest;
System.out.println("Interest applied: $" + interest);
}
}
// Current Account
public class CurrentAccount extends Account {
private double overdraftLimit;
public CurrentAccount(String accountNumber, String holderName,
double overdraftLimit) {
super(accountNumber, holderName, "Current");
this.overdraftLimit = overdraftLimit;
}
@Override
public boolean withdraw(double amount) {
if (amount > 0 && (balance + overdraftLimit) >= amount) {
balance -= amount;
System.out.println("Withdrawn: $" + amount);
if (balance < 0) {
System.out.println("Account overdrawn by: $" + Math.abs(balance));
}
return true;
}
System.out.println("Withdrawal exceeds overdraft limit!");
return false;
}
@Override
public double calculateInterest() {
return 0.0; // No interest for current account
}
}Method Overriding vs Method Overloading
Method Overriding:
- Same method signature in parent and child
- Runtime polymorphism
- Uses inheritance
- @Override annotation
- Method resolution at runtime
class Animal {
public void makeSound() {
System.out.println("Animal sound");
}
}
class Dog extends Animal {
@Override // Same signature
public void makeSound() {
System.out.println("Woof!");
}
}
// Usage:
Animal animal = new Dog();
animal.makeSound(); // Prints "Woof!" - Runtime decisionMethod Overloading:
- Same method name, different parameters
- Compile-time polymorphism
- Within same class
- No special annotation
- Method resolution at compile time
class Calculator {
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) { // Different parameters
return a + b;
}
public int add(int a, int b, int c) { // Different parameter count
return a + b + c;
}
}
// Usage:
Calculator calc = new Calculator();
calc.add(5, 3); // Calls int version
calc.add(5.5, 3.2); // Calls double version
calc.add(1, 2, 3); // Calls three-parameter version| Aspect | Method Overriding | Method Overloading |
|---|---|---|
| Purpose | Provide specific implementation | Multiple ways to call method |
| Inheritance | Required (parent-child) | Not required (same class) |
| Method Signature | Must be identical | Must be different |
| Polymorphism Type | Runtime | Compile-time |
| Performance | Slightly slower (dynamic binding) | Faster (static binding) |
Previous Year Exam Questions
Q1. (GTU Summer 2022) Explain inheritance in Java with its types. Write a program to demonstrate method overriding with a practical example.
Solution:
Inheritance in Java:
Inheritance is a fundamental OOP concept where a new class (subclass) acquires properties and methods from an existing class (superclass). It promotes code reusability and establishes an "is-a" relationship.
Types of Inheritance:
1. Single Inheritance:
One class extends another class directly.
2. Multilevel Inheritance:
A class extends another class which itself extends another class, forming a chain.
3. Hierarchical Inheritance:
Multiple classes inherit from a single superclass.
Method Overriding Program - Employee Management System:
// Base class
class Employee {
protected String name;
protected int empId;
protected double basicSalary;
protected String department;
public Employee(String name, int empId, double basicSalary, String department) {
this.name = name;
this.empId = empId;
this.basicSalary = basicSalary;
this.department = department;
}
// Method to be overridden
public double calculateSalary() {
return basicSalary;
}
// Method to be overridden
public void displayDetails() {
System.out.println("=== Employee Details ===");
System.out.println("Name: " + name);
System.out.println("ID: " + empId);
System.out.println("Department: " + department);
System.out.println("Basic Salary: $" + basicSalary);
System.out.println("Total Salary: $" + calculateSalary());
}
// Common method for all employees
public void work() {
System.out.println(name + " is working in " + department + " department");
}
}
// Derived class 1 - Manager
class Manager extends Employee {
private double allowance;
private int teamSize;
public Manager(String name, int empId, double basicSalary,
String department, double allowance, int teamSize) {
super(name, empId, basicSalary, department); // Call parent constructor
this.allowance = allowance;
this.teamSize = teamSize;
}
// Override calculateSalary method
@Override
public double calculateSalary() {
double teamBonus = teamSize * 500; // $500 per team member
return basicSalary + allowance + teamBonus;
}
// Override displayDetails method
@Override
public void displayDetails() {
super.displayDetails(); // Call parent method
System.out.println("Position: Manager");
System.out.println("Team Size: " + teamSize);
System.out.println("Allowance: $" + allowance);
System.out.println("Team Bonus: $" + (teamSize * 500));
System.out.println("========================");
}
// Manager-specific method
public void conductMeeting() {
System.out.println("Manager " + name + " is conducting a team meeting");
}
}
// Derived class 2 - Developer
class Developer extends Employee {
private String programmingLanguage;
private int projectsCompleted;
public Developer(String name, int empId, double basicSalary,
String department, String programmingLanguage, int projectsCompleted) {
super(name, empId, basicSalary, department);
this.programmingLanguage = programmingLanguage;
this.projectsCompleted = projectsCompleted;
}
// Override calculateSalary method
@Override
public double calculateSalary() {
double projectBonus = projectsCompleted * 1000; // $1000 per project
double skillBonus = 2000; // Fixed skill bonus
return basicSalary + projectBonus + skillBonus;
}
// Override displayDetails method
@Override
public void displayDetails() {
super.displayDetails();
System.out.println("Position: Developer");
System.out.println("Programming Language: " + programmingLanguage);
System.out.println("Projects Completed: " + projectsCompleted);
System.out.println("Project Bonus: $" + (projectsCompleted * 1000));
System.out.println("Skill Bonus: $2000");
System.out.println("========================");
}
// Developer-specific method
public void writeCode() {
System.out.println("Developer " + name + " is writing code in " + programmingLanguage);
}
}
// Derived class 3 - Intern
class Intern extends Employee {
private int duration; // in months
private String university;
public Intern(String name, int empId, double basicSalary,
String department, int duration, String university) {
super(name, empId, basicSalary, department);
this.duration = duration;
this.university = university;
}
// Override calculateSalary method
@Override
public double calculateSalary() {
// Interns get basic salary + completion bonus if duration > 6 months
double completionBonus = (duration > 6) ? 1500 : 0;
return basicSalary + completionBonus;
}
// Override displayDetails method
@Override
public void displayDetails() {
super.displayDetails();
System.out.println("Position: Intern");
System.out.println("University: " + university);
System.out.println("Duration: " + duration + " months");
if (duration > 6) {
System.out.println("Completion Bonus: $1500");
}
System.out.println("========================");
}
// Intern-specific method
public void attendTraining() {
System.out.println("Intern " + name + " is attending training sessions");
}
}
// Main class to demonstrate method overriding
public class InheritanceDemo {
public static void main(String[] args) {
System.out.println("=== Inheritance and Method Overriding Demo ===\n");
// Create different types of employees
Manager manager = new Manager("Alice Johnson", 101, 60000, "IT", 15000, 8);
Developer developer = new Developer("Bob Smith", 102, 50000, "Development", "Java", 12);
Intern intern = new Intern("Charlie Brown", 103, 15000, "IT", 8, "State University");
// Store in array for polymorphic behavior
Employee[] employees = {manager, developer, intern};
System.out.println("=== Employee Information ===\n");
// Demonstrate polymorphism and method overriding
for (Employee emp : employees) {
emp.displayDetails(); // Different implementation for each type
emp.work(); // Common method
System.out.println();
}
// Demonstrate specific methods
System.out.println("=== Specific Employee Actions ===");
manager.conductMeeting();
developer.writeCode();
intern.attendTraining();
// Calculate total payroll
System.out.println("\n=== Payroll Summary ===");
double totalPayroll = 0;
for (Employee emp : employees) {
double salary = emp.calculateSalary(); // Overridden method called
totalPayroll += salary;
System.out.printf("%s (ID: %d): $%.2f\n", emp.name, emp.empId, salary);
}
System.out.printf("\nTotal Company Payroll: $%.2f\n", totalPayroll);
// Demonstrate runtime polymorphism
System.out.println("\n=== Runtime Polymorphism Demo ===");
Employee emp1 = new Manager("David Wilson", 104, 55000, "Sales", 12000, 5);
Employee emp2 = new Developer("Eva Davis", 105, 48000, "Development", "Python", 8);
// Reference type is Employee, but actual object determines method called
System.out.println("emp1 salary: $" + emp1.calculateSalary()); // Manager's method
System.out.println("emp2 salary: $" + emp2.calculateSalary()); // Developer's method
}
}Q2. (GTU Winter 2021) What is the use of 'super' keyword in Java? Explain with examples including constructor chaining.
Solution:
The 'super' Keyword in Java:
The 'super' keyword is a reference variable that refers to the immediate parent class object. It is used to access parent class members from child class.
Uses of 'super' Keyword:
1. Access Parent Class Variables:
class Vehicle {
protected String brand = "Generic Vehicle";
protected int maxSpeed = 100;
}
class Car extends Vehicle {
private String brand = "Toyota"; // Hides parent's brand
private int maxSpeed = 180; // Hides parent's maxSpeed
public void displayInfo() {
System.out.println("Car brand: " + this.brand); // Child's brand
System.out.println("Vehicle brand: " + super.brand); // Parent's brand
System.out.println("Car max speed: " + this.maxSpeed); // Child's maxSpeed
System.out.println("Vehicle max speed: " + super.maxSpeed); // Parent's maxSpeed
}
}2. Call Parent Class Methods:
class Animal {
public void eat() {
System.out.println("Animal is eating food");
}
public void sleep() {
System.out.println("Animal is sleeping");
}
}
class Dog extends Animal {
@Override
public void eat() {
super.eat(); // Call parent's eat method first
System.out.println("Dog is eating dog food");
}
public void displayBehavior() {
super.sleep(); // Call parent's sleep method
this.eat(); // Call overridden eat method
}
}3. Constructor Chaining with 'super':
// Base class
class Person {
protected String name;
protected int age;
protected String address;
// Default constructor
public Person() {
this.name = "Unknown";
this.age = 0;
this.address = "Not specified";
System.out.println("Person default constructor called");
}
// Parameterized constructor
public Person(String name, int age) {
this.name = name;
this.age = age;
this.address = "Not specified";
System.out.println("Person constructor (name, age) called");
}
// Full constructor
public Person(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
System.out.println("Person full constructor called");
}
public void displayPersonInfo() {
System.out.println("Name: " + name);
System.out.println("Age: " + age);
System.out.println("Address: " + address);
}
}
// Derived class
class Student extends Person {
private String studentId;
private String course;
private double gpa;
// Constructor 1: Default
public Student() {
super(); // Call parent's default constructor (optional - called automatically)
this.studentId = "STU000";
this.course = "General";
this.gpa = 0.0;
System.out.println("Student default constructor called");
}
// Constructor 2: Basic info
public Student(String name, int age, String studentId) {
super(name, age); // Call parent's parameterized constructor
this.studentId = studentId;
this.course = "General";
this.gpa = 0.0;
System.out.println("Student basic constructor called");
}
// Constructor 3: Full info
public Student(String name, int age, String address,
String studentId, String course, double gpa) {
super(name, age, address); // Call parent's full constructor
this.studentId = studentId;
this.course = course;
this.gpa = gpa;
System.out.println("Student full constructor called");
}
@Override
public void displayPersonInfo() {
super.displayPersonInfo(); // Call parent method
System.out.println("Student ID: " + studentId);
System.out.println("Course: " + course);
System.out.println("GPA: " + gpa);
}
public void study() {
System.out.println(name + " is studying " + course);
}
}
// Further derived class
class GraduateStudent extends Student {
private String researchTopic;
private String advisor;
public GraduateStudent(String name, int age, String address,
String studentId, String course, double gpa,
String researchTopic, String advisor) {
super(name, age, address, studentId, course, gpa); // Chain to Student constructor
this.researchTopic = researchTopic;
this.advisor = advisor;
System.out.println("GraduateStudent constructor called");
}
@Override
public void displayPersonInfo() {
super.displayPersonInfo(); // Call Student's method (which calls Person's)
System.out.println("Research Topic: " + researchTopic);
System.out.println("Advisor: " + advisor);
}
@Override
public void study() {
super.study(); // Call Student's study method
System.out.println(name + " is also conducting research on " + researchTopic);
}
}
// Demo class
public class SuperKeywordDemo {
public static void main(String[] args) {
System.out.println("=== Constructor Chaining Demo ===\n");
System.out.println("Creating Student with default constructor:");
Student student1 = new Student();
student1.displayPersonInfo();
System.out.println();
System.out.println("Creating Student with basic constructor:");
Student student2 = new Student("John Doe", 20, "STU001");
student2.displayPersonInfo();
System.out.println();
System.out.println("Creating Student with full constructor:");
Student student3 = new Student("Jane Smith", 22, "123 Main St",
"STU002", "Computer Science", 3.8);
student3.displayPersonInfo();
System.out.println();
System.out.println("Creating GraduateStudent (multilevel inheritance):");
GraduateStudent gradStudent = new GraduateStudent(
"Alice Johnson", 25, "456 Oak Ave", "GRAD001",
"Computer Science", 3.9, "Machine Learning", "Dr. Brown");
gradStudent.displayPersonInfo();
System.out.println();
System.out.println("=== Method Calls with super ===");
gradStudent.study();
System.out.println("\n=== Summary of 'super' Usage ===");
System.out.println("1. super() - calls parent constructor (must be first statement)");
System.out.println("2. super.variable - accesses parent class variable");
System.out.println("3. super.method() - calls parent class method");
System.out.println("4. Constructor chaining creates proper initialization hierarchy");
}
}Key Points about 'super' Keyword:
- Constructor Chaining: super() must be the first statement in child constructor
- Automatic Call: If super() is not explicit, Java automatically calls super()
- Variable Access: Useful when child hides parent variables
- Method Enhancement: Call parent method and add additional functionality
- Multilevel Inheritance: Each level calls its immediate parent
Q3. (GTU Summer 2020) Differentiate between method overriding and method overloading with suitable examples.
Solution:
Method Overriding vs Method Overloading:
| Aspect | Method Overriding | Method Overloading |
|---|---|---|
| Definition | Redefining parent method in child class | Multiple methods with same name, different parameters |
| Inheritance Required | Yes (parent-child relationship) | No (same class) |
| Method Signature | Must be identical | Must be different (parameters) |
| Polymorphism Type | Runtime (Dynamic) | Compile-time (Static) |
| Binding | Late binding | Early binding |
| Performance | Slightly slower | Faster |
| Access Modifier | Cannot reduce visibility | Can have any access modifier |
| Return Type | Same or covariant | Can be different |
Method Overriding Example:
// Method Overriding - Runtime Polymorphism
class Shape {
public void draw() {
System.out.println("Drawing a generic shape");
}
public double getArea() {
return 0.0;
}
public void displayInfo() {
System.out.println("Shape information");
System.out.println("Area: " + getArea()); // Will call overridden version
}
}
class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override // Method Overriding
public void draw() {
System.out.println("Drawing a circle with radius " + radius);
}
@Override // Method Overriding
public double getArea() {
return Math.PI * radius * radius;
}
// Additional method specific to Circle
public double getCircumference() {
return 2 * Math.PI * radius;
}
}
class Rectangle extends Shape {
private double width, height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override // Method Overriding
public void draw() {
System.out.println("Drawing a rectangle " + width + "x" + height);
}
@Override // Method Overriding
public double getArea() {
return width * height;
}
// Additional method specific to Rectangle
public double getPerimeter() {
return 2 * (width + height);
}
}Method Overloading Example:
// Method Overloading - Compile-time Polymorphism
class Calculator {
// Method Overloading - Different number of parameters
public int add(int a, int b) {
System.out.println("Adding two integers");
return a + b;
}
public int add(int a, int b, int c) {
System.out.println("Adding three integers");
return a + b + c;
}
// Method Overloading - Different parameter types
public double add(double a, double b) {
System.out.println("Adding two doubles");
return a + b;
}
public String add(String a, String b) {
System.out.println("Concatenating two strings");
return a + b;
}
// Method Overloading - Different parameter order
public void display(int a, String b) {
System.out.println("Integer: " + a + ", String: " + b);
}
public void display(String a, int b) {
System.out.println("String: " + a + ", Integer: " + b);
}
// Method Overloading with varargs
public int add(int... numbers) {
System.out.println("Adding " + numbers.length + " integers using varargs");
int sum = 0;
for (int num : numbers) {
sum += num;
}
return sum;
}
}Demonstration Program:
public class OverridingVsOverloadingDemo {
public static void main(String[] args) {
System.out.println("=== Method Overriding Demo ===");
// Runtime Polymorphism - Method determined at runtime
Shape shape1 = new Circle(5.0);
Shape shape2 = new Rectangle(4.0, 6.0);
Shape shape3 = new Shape();
Shape[] shapes = {shape1, shape2, shape3};
for (Shape shape : shapes) {
shape.draw(); // Different method called for each object
shape.displayInfo(); // Different area calculation
System.out.println("---");
}
System.out.println("\n=== Method Overloading Demo ===");
Calculator calc = new Calculator();
// Method determined at compile time based on parameters
System.out.println("Result: " + calc.add(5, 3)); // Two int
System.out.println("Result: " + calc.add(5, 3, 2)); // Three int
System.out.println("Result: " + calc.add(5.5, 3.2)); // Two double
System.out.println("Result: " + calc.add("Hello ", "World")); // Two String
calc.display(10, "Test"); // int, String
calc.display("Test", 10); // String, int
System.out.println("Result: " + calc.add(1, 2, 3, 4, 5)); // Varargs
System.out.println("\n=== Key Differences Summary ===");
System.out.println("Method Overriding:");
System.out.println("- Requires inheritance");
System.out.println("- Same method signature");
System.out.println("- Runtime decision (dynamic binding)");
System.out.println("- Enables runtime polymorphism");
System.out.println("\nMethod Overloading:");
System.out.println("- Same class");
System.out.println("- Different method signature");
System.out.println("- Compile-time decision (static binding)");
System.out.println("- Enables compile-time polymorphism");
}
}Hands-on Lab Exercises
Exercise 1: Vehicle Hierarchy System
- Create a comprehensive vehicle inheritance hierarchy:
- Base Vehicle class with common properties and methods
- LandVehicle, WaterVehicle, AirVehicle subclasses
- Specific vehicles: Car, Truck, Boat, Ship, Airplane, Helicopter
- Implement method overriding for start(), stop(), move() methods
- Include proper constructor chaining and super keyword usage
- Demonstrate polymorphism with arrays of different vehicle types
Exercise 2: Educational Institution Management
- Design a complete educational system:
- Person base class with common attributes
- Student, Teacher, Administrator subclasses
- Specialized classes: GraduateStudent, Professor, Principal
- Override methods like displayInfo(), calculateFees(), getSalary()
- Implement method overloading for multiple constructors and utility methods
- Create interactive system for managing different person types
Exercise 3: Media Library System
- Build a media management system:
- Media base class with common properties
- Book, Movie, Music, Game subclasses
- Override methods: play(), display(), calculateRentalCost()
- Implement different rental pricing strategies
- Include method overloading for search and filter operations
- Demonstrate inheritance benefits in code maintenance
Lecture Summary
Key Concepts Covered:
- Inheritance fundamentals and types
- Method overriding and runtime polymorphism
- Super keyword for parent access
- Constructor chaining in inheritance
- Access modifiers in inheritance hierarchy
- Method overriding vs method overloading
- Real-world inheritance design patterns
Learning Outcomes Achieved:
- ✅ Master inheritance concept and implementation
- ✅ Apply method overriding for polymorphism
- ✅ Use super keyword effectively
- ✅ Design inheritance hierarchies properly
- ✅ Understand access control in inheritance
- ✅ Distinguish overriding from overloading
- ✅ Build scalable object-oriented systems
Next Lecture: Polymorphism and Abstract Classes
Topics: Runtime polymorphism, abstract classes, abstract methods, interface introduction
Thank You!
Questions & Discussion
Next: Lecture 11 - Polymorphism and Abstract Classes
Course: 4343203 Java Programming
Unit 2: Object-Oriented Programming
GTU Semester 4

