Welcome, students! In this lesson, we will learn about two very important concepts in Object-Oriented Programming: Inheritance and Polymorphism. These concepts help us write better, reusable, and more organized code. Let’s begin our journey!
1. Introduction to Inheritance
1.1 Why Object-Oriented Programming is Popular
Object-oriented programming (OOP) is very popular among programmers for several important reasons:
- Code Reuse: We can use code that was written before and saved as classes. We don’t need to write everything from scratch.
- Class Hierarchy: All Java classes are arranged in a hierarchy (like a family tree).
- Object Class: The
Objectclass is the superclass of all Java classes. Every class in Java inherits from the Object class. - Extension and Refinement: Inheritance allows us to create new things that are extensions or improvements of existing things.
1.2 What is Inheritance?
Let’s understand inheritance step by step:
Definition: Inheritance is a mechanism in which one object acquires all the properties and behaviors of a parent object.
Imagine you have written code for a class called “Vehicle.” Now you want to create a class called “Car.” Instead of writing all the code again for Car, you can simply “inherit” all the features of Vehicle and add only the new features that are specific to Car. This is the power of inheritance!
Key Terms to Remember:
| Term | Meaning |
|---|---|
| Superclass / Base Class / Parent Class | The existing (old) class that is being inherited from |
| Subclass / Derived Class / Child Class | The new class that inherits from the superclass |
| extends | Keyword used to show inheritance in Java |
| implements | Keyword used to implement an interface |
+----------------+
| Superclass | (Parent/Base Class)
| (A) |
+-------+--------+
|
| extends
|
+-------v--------+
| Subclass | (Child/Derived Class)
| (B) |
+----------------+
1.3 Declaring Subclasses in Java
In Java, we use the reserved word extends to establish an inheritance relationship.
Syntax:
class SubclassName extends SuperclassName {
// class contents
}
Example:
class Car extends Vehicle {
// Car inherits all properties and methods from Vehicle
// You can add new properties and methods here
}
Exam Question 1: What is inheritance in Java? Explain with an example why it is useful in programming.
Answer:
Inheritance is a mechanism in Java where a new class (subclass) acquires all the properties and behaviors of an existing class (superclass). It is useful because:
- It promotes code reusability – we don’t need to rewrite code
- It saves development time
- It helps organize code in a hierarchical structure
- It makes code easier to maintain
Example: If we have a class “Animal” with methods like eat() and sleep(), we can create a class “Dog” that extends Animal. The Dog class automatically gets eat() and sleep() methods without rewriting them.
2. Types of Inheritance
Java supports several types of inheritance. Let’s understand each type with diagrams and examples.
2.1 Single Inheritance
In single inheritance, a subclass inherits from only one superclass.
+--------+
| A | (Superclass)
+---+----+
|
| extends
|
+---v----+
| B | (Subclass)
+--------+
Example:
class Animal {
void eat() {
System.out.println("Animal eats");
}
}
class Dog extends Animal { // Single inheritance
void bark() {
System.out.println("Dog barks");
}
}
2.2 Multiple Inheritance
In multiple inheritance, a subclass inherits from multiple superclasses. However, Java does NOT support multiple inheritance with classes (to avoid complexity and ambiguity).
+--------+ +--------+
| A | | B | (Two Superclasses)
+---+----+ +---+----+
| |
+------+-------+
|
| extends (NOT supported in Java with classes)
|
+------v-------+
| C | (Subclass)
+--------------+
2.3 Hierarchical Inheritance
In hierarchical inheritance, one superclass has multiple subclasses.
+--------+
| A | (Superclass)
+---+----+
|
+--------+--------+
| | |
+---v--+ +--v---+ +-v----+
| B | | C | | D | (Multiple Subclasses)
+------+ +------+ +------+
Example:
class Vehicle {
void start() {
System.out.println("Vehicle starts");
}
}
class Car extends Vehicle { } // Hierarchical inheritance
class Bike extends Vehicle { } // Hierarchical inheritance
class Truck extends Vehicle { } // Hierarchical inheritance
2.4 Multi-Level Inheritance
In multi-level inheritance, a subclass becomes the superclass for another class. It forms a chain.
+--------+
| A | (Superclass)
+---+----+
|
| extends
|
+---v----+
| B | (Subclass of A, Superclass of C)
+---+----+
|
| extends
|
+---v----+
| C | (Subclass of B)
+--------+
Example:
class Animal {
void eat() { }
}
class Mammal extends Animal { // Mammal is subclass of Animal
void breathe() { }
}
class Dog extends Mammal { // Dog is subclass of Mammal
void bark() { }
}
// Dog inherits from both Mammal and Animal
2.5 Hybrid Inheritance
Hybrid inheritance is a combination of two or more types of inheritance. Java does not support hybrid inheritance with classes directly.
+--------+
| A |
+---+----+
|
+-----+-----+
| |
+---v---+ +---v---+
| B | | C |
+---+---+ +---+---+
| |
+-----+-----+
|
+---v---+
| D |
+-------+
2.6 Multi-Path Inheritance
In multi-path inheritance, a subclass inherits from multiple paths. This creates ambiguity and is not supported in Java with classes.
+--------+
| A |
+---+----+
|
+-----+-----+
| |
+---v---+ +---v---+
| B | | C |
+---+---+ +---+---+
| |
+-----+-----+
|
+---v---+
| D | (Inherits from A via B and C - two paths)
+-------+
Exam Question 2: Why does Java NOT support multiple inheritance with classes? How can we achieve similar functionality in Java?
Answer:
Java does not support multiple inheritance with classes because it creates ambiguity. Consider this scenario:
- Class B and Class C both have a method called display()
- Class D extends both B and C
- When D calls display(), which version should be called? B’s or C’s?
This creates confusion called the “Diamond Problem.”
Solution: Java allows multiple inheritance through interfaces. Since interfaces only declare methods (no implementation until Java 8’s default methods), there’s no ambiguity. The implementing class provides the actual implementation.
3. Benefits of Inheritance
Inheritance provides several important benefits that make programming easier and more efficient:
3.1 Code Reusability
Detailed Explanation:
Inheritance automates the process of reusing code from superclasses in subclasses. When a subclass inherits from a superclass, it automatically gets all the public and protected methods and variables. This means:
- No need to rewrite the same code
- Saves development time
- Reduces redundancy in programming
- An object can inherit general properties from its parent
3.2 Code Maintenance
Organizing code into hierarchical classes makes it easier to:
- Find and fix bugs
- Add new features
- Understand the code structure
- Manage large projects
3.3 Implementing OOP Philosophy
Inheritance helps implement the basic OOP philosophy to adapt computing to the problem (not the other way around). This is because entities (objects) in the real world are often organized into a hierarchy.
Example from Real World:
- Living Thing → Animal → Mammal → Dog
- Vehicle → Car → Sports Car
3.4 Increased Reliability
When we reuse well-tested code from superclasses, our programs become more reliable. The superclass code has already been tested and proven to work correctly.
- Inheritance creates an “IS-A” relationship (a Car IS-A Vehicle)
- The “extends” keyword is used for class inheritance
- Inheritance promotes code reuse and reduces redundancy
- All Java classes ultimately inherit from the Object class
Exam Question 3: A programmer creates a class “Employee” with methods calculateSalary() and displayInfo(). Then creates a class “Manager” that extends Employee. What benefits does the Manager class get from inheritance?
Answer:
The Manager class receives the following benefits:
- Automatic Method Access: Manager automatically has calculateSalary() and displayInfo() methods without rewriting them
- Code Reusability: No need to duplicate code for common employee features
- Easy Maintenance: If calculateSalary() logic changes, it only needs to be updated in Employee class
- Extensibility: Manager can add its own specific methods like manageTeam() while keeping inherited methods
- Polymorphism: A Manager object can be treated as an Employee object
4. Method Overloading
4.1 What is Method Overloading?
Method overloading occurs when two or more methods in the same class have the same name but different parameters.
Detailed Explanation:
Think of method overloading like having multiple tools with the same name but different purposes. For example, a “print” method might print an integer, a double, or a String. The name is the same, but what it does depends on what you give it (the parameters).
4.2 Ways to Overload Methods
There are two main ways to overload a method in Java:
1. By changing the number of arguments:
void add(int a, int b) // Takes 2 arguments void add(int a, int b, int c) // Takes 3 arguments
2. By changing the data type of arguments:
void add(int a, int b) // Takes integers void add(double a, double b) // Takes doubles
4.3 Complete Example of Method Overloading
class Sum {
// Method 1: Adds two integers
void add(int a, int b) {
System.out.println("Sum of two = " + (a + b));
}
// Method 2: Adds three doubles (different number of parameters)
void add(double a, double b, double c) {
System.out.println("Sum of three = " + (a + b + c));
}
}
class OverLoad {
public static void main(String[] args) {
Sum s = new Sum();
s.add(20, 25); // Calls Method 1
s.add(10.1, 12.8, 7.1); // Calls Method 2
}
}
Output:
Sum of two = 45 Sum of three = 30.0
- Overloading happens within the SAME class
- Method name must be the SAME
- Parameters must be DIFFERENT (number or type)
- Return type can be different, but it’s not enough by itself
- Overloading is resolved at COMPILE TIME (static binding)
Exam Question 4: Consider the following code. Will this compile? Why or why not?
class Test {
int calculate(int a, int b) { return a + b; }
double calculate(int a, int b) { return a + b + 0.5; }
}
Answer:
No, this will NOT compile.
Explanation: The two methods have the same name and the same parameter list (int a, int b). Changing only the return type is NOT sufficient for method overloading. Java considers two methods to be the same if they have the same name and parameter list, regardless of return type.
This creates a “duplicate method” error because the compiler cannot distinguish between them based on return type alone.
To fix this: You must change the parameter list:
int calculate(int a, int b) { return a + b; }
double calculate(double a, double b) { return a + b; } // Different parameters
5. Method Overriding
5.1 What is Method Overriding?
Method overriding occurs when a subclass provides a new implementation for a method that is already defined in its superclass.
Detailed Explanation:
Think of method overriding like a child improving upon a skill learned from a parent. The parent knows how to cook, but the child (who learned cooking from the parent) develops their own special cooking style. The method name is the same, but the implementation is different and specific to the child class.
5.2 Rules for Method Overriding
- Both methods must have the same name
- Both methods must have the same parameters
- Both methods must have the same return type
- The method in the subclass cannot have more restrictive access
- Only instance methods can be overridden (not static methods)
5.3 Complete Example of Method Overriding
// Parent class
class Animal {
void move() {
System.out.println("Animals can move");
}
}
// Child class
class Dog extends Animal {
// Overriding the move() method
void move() {
System.out.println("Dogs can walk and run");
}
}
// Main class
public class OverRide {
public static void main(String args[]) {
Animal a = new Animal(); // Animal reference and object
Animal b = new Dog(); // Animal reference but Dog object
a.move(); // Runs the method in Animal class
b.move(); // Runs the method in Dog class (overridden version)
}
}
Output:
Animals can move Dogs can walk and run
5.4 Benefits of Method Overriding
- Specific Behavior: Subclass can define behavior specific to its type
- Flexibility: Same method name can work differently for different classes
- Runtime Polymorphism: Enables polymorphic behavior at runtime
Exam Question 5: What is the output of the following code?
class Parent {
void show() { System.out.println("Parent"); }
}
class Child extends Parent {
void show() { System.out.println("Child"); }
}
class Test {
public static void main(String[] args) {
Parent p = new Child();
p.show();
}
}
Answer: The output is “Child”
Explanation:
- The reference variable ‘p’ is of type Parent
- The actual object created is of type Child
- In method overriding, Java determines which method to call based on the actual object type at runtime, not the reference type
- Since the actual object is Child, the Child’s show() method is called
- This is an example of runtime polymorphism or dynamic method dispatch
6. Difference Between Overloading and Overriding
| Aspect | Method Overloading | Method Overriding |
|---|---|---|
| Definition | Same method name, different parameters in same class | Same method name and parameters in subclass |
| Location | Within the same class | Between superclass and subclass |
| Parameters | Must be different | Must be the same |
| Return Type | Can be different | Must be same (or covariant) |
| Binding | Static (compile time) | Dynamic (runtime) |
| Polymorphism Type | Compile-time polymorphism | Runtime polymorphism |
| Performance | Faster (resolved at compile time) | Slower (resolved at runtime) |
Exam Question 6: Identify whether each scenario is overloading or overriding:
a) Class A has method calculate(int x) and calculate(int x, int y)
b) Class Parent has method display() and Class Child (extends Parent) has method display() with same signature
c) Class Calculator has method add(int a, int b) and add(double a, double b)
Answers:
a) Overloading – Same class, same method name, different parameters (one int vs two ints)
b) Overriding – Different classes (inheritance relationship), same method signature
c) Overloading – Same class, same method name, different parameter types (int vs double)
7. Polymorphism
7.1 What is Polymorphism?
The word “polymorphism” comes from Greek words:
- Poly = Many
- Morph = Forms
Definition: Polymorphism is the ability of a method to take more than one form to perform several tasks.
Detailed Explanation:
A polymorphic reference is a variable that can refer to different types of objects at different points in time. For example, an Animal reference can point to a Dog object, a Cat object, or a Bird object. When you call a method on this reference, the appropriate method for the actual object type is executed.
7.2 Types of Polymorphism
POLYMORPHISM
|
+--------------+--------------+
| |
Static Polymorphism Dynamic Polymorphism
(Compile-time) (Runtime)
| |
Method Overloading Method Overriding
7.3 Static Polymorphism (Compile-Time Polymorphism)
Characteristics:
- Resolved at compile time
- Compiler knows which method will be called
- Also called static binding or early binding
- Method overloading is an example
Example:
class Animal {
static void move() {
System.out.println("Animals can move");
}
}
class Dog extends Animal {
static void move() {
System.out.println("Dogs can walk and run");
}
}
public class StaticPoly {
public static void main(String args[]) {
Animal.move(); // Calls Animal's move()
Dog.move(); // Calls Dog's move()
}
}
Output:
Animals can move Dogs can walk and run
7.4 Dynamic Polymorphism (Runtime Polymorphism)
Characteristics:
- Resolved at runtime (when program is running)
- JVM determines which method to call based on the actual object
- Also called dynamic binding or late binding
- Method overriding is an example
Example:
class Animal {
void move() {
System.out.println("Animals can move");
}
}
class Dog extends Animal {
void move() { // This overrides the parent's move()
System.out.println("Dogs can walk and run");
}
}
public class DynamicPoly {
public static void main(String args[]) {
Animal a = new Dog(); // Reference is Animal, Object is Dog
a.move(); // Which move() is called? Dog's move()!
}
}
Output:
Dogs can walk and run
The Java compiler doesn’t know which move() method will be called when compiling the code. It only knows that ‘a’ is an Animal reference. At runtime, the JVM looks at the actual object (which is a Dog) and calls the appropriate method. This decision is made “dynamically” during program execution.
Exam Question 7: What is the difference between static binding and dynamic binding? Give one example of each.
Answer:
| Static Binding | Dynamic Binding |
|---|---|
| Resolved at compile time | Resolved at runtime |
| Compiler knows which method to call | JVM decides which method to call |
| Faster execution | Slower execution |
| Used for: private, static, final methods | Used for: overridden methods |
| Example: Method overloading | Example: Method overriding |
Static Binding Example: When you call Math.max(5, 10), the compiler knows exactly which max method to call at compile time.
Dynamic Binding Example: When you have Animal a = new Dog(); a.move(); – the compiler doesn’t know which move() will be called until runtime.
8. The super Keyword
8.1 What is the super Keyword?
The super keyword in Java is a reference variable that refers to the immediate parent class object. It is used when we want to access members (variables, methods, or constructors) of the parent class.
8.2 Uses of super Keyword
1. To call the superclass constructor:
// Call parameterized constructor of superclass super(parameter-list); // Call no-argument constructor of superclass super();
2. To access members of the superclass:
// Access variable or method of superclass super.memberName;
8.3 Example: Using super to Call Parent Method
class Animal {
public void move() {
System.out.println("Animals can move");
}
}
class Dog extends Animal {
public void move() {
super.move(); // Calls the parent class method
System.out.println("Dogs can walk and run");
}
}
public class TestDog {
public static void main(String args[]) {
Animal b = new Dog(); // Animal reference but Dog object
b.move(); // Runs the method in Dog class
}
}
Output:
Animals can move Dogs can walk and run
8.4 Example: Using super to Call Parent Constructor
class Parent {
int x;
Parent(int a) {
x = a;
System.out.println("Parent constructor called");
}
}
class Child extends Parent {
int y;
Child(int a, int b) {
super(a); // Must be first statement
y = b;
System.out.println("Child constructor called");
}
}
- super() must be the FIRST statement in the constructor
- If you don’t write super(), Java automatically adds super() (calls no-arg parent constructor)
- You cannot use both super() and this() in the same constructor
Exam Question 8: What happens if a subclass constructor doesn’t explicitly call super()?
Answer:
If a subclass constructor doesn’t explicitly call super(), Java automatically inserts a call to the no-argument constructor of the superclass (super()) as the first statement.
However, there’s a problem if:
- The parent class doesn’t have a no-argument constructor
- The parent class only has parameterized constructors
In this case, you MUST explicitly call super(parameters) to match one of the parent’s constructors, otherwise you’ll get a compilation error.
Example:
class Parent {
Parent(int x) { } // Only parameterized constructor
}
class Child extends Parent {
Child() {
// Error! Java tries to call super() but Parent has no no-arg constructor
// Fix: super(5); must be added
}
}
9. Abstract Classes
9.1 What is an Abstract Class?
Before understanding abstract classes, let’s understand two types of methods:
- Concrete Method: A method with a body (implementation)
- Abstract Method: A method without a body (no implementation)
Definition: An abstract class is a class that contains zero or more abstract methods. It represents a general concept that cannot be instantiated directly.
Detailed Explanation:
Think of an abstract class like a “template” or “blueprint” that is incomplete. For example, “Shape” is an abstract concept – you cannot draw a generic “shape.” But you can draw a Rectangle, Circle, or Triangle. The Shape class defines common properties (like area, perimeter) that all shapes have, but the specific calculations are different for each type of shape.
9.2 Syntax for Abstract Class
abstract class ClassName {
// Concrete methods (with body)
void normalMethod() {
// implementation
}
// Abstract methods (without body)
abstract void abstractMethod();
}
9.3 Syntax for Abstract Method
// Abstract method declaration public abstract void methodName(); // OR with parameters public abstract void methodName(parameterList);
- Abstract methods have NO body – they end with a semicolon, not curly braces
- The abstract keyword must be used for both the class and abstract methods
- You CANNOT create objects of an abstract class (cannot instantiate)
- Subclasses MUST implement all abstract methods (unless the subclass is also abstract)
9.4 Why Use Abstract Classes?
- Define Common Behavior: Abstract classes let you define methods that all subclasses will have
- Force Implementation: Abstract methods force subclasses to provide specific implementations
- Cannot Instantiate: You cannot create objects of abstract classes, ensuring the concept remains abstract
9.5 Complete Example of Abstract Class
// Abstract class
abstract class Figure {
double dim1;
double dim2;
Figure(double a, double b) {
dim1 = a;
dim2 = b;
}
// Abstract method - no body
abstract double area();
}
// Concrete subclass 1
class Rectangle extends Figure {
Rectangle(double a, double b) {
super(a, b); // Call parent constructor
}
// Must implement abstract method
double area() {
System.out.println("Inside Area of Rectangle.");
return dim1 * dim2;
}
}
// Concrete subclass 2
class Triangle extends Figure {
Triangle(double a, double b) {
super(a, b);
}
// Must implement abstract method
double area() {
System.out.println("Inside Area of Triangle.");
return dim1 * dim2 / 2;
}
}
// Main class
class AbstractAreas {
public static void main(String args[]) {
Rectangle r = new Rectangle(9, 5);
Triangle t = new Triangle(10, 8);
System.out.println("Area is " + r.area()); // Output: 45
System.out.println("Area is " + t.area()); // Output: 40
}
}
9.6 Important Rules for Abstract Classes
- A class cannot be both
abstractandfinal - Abstract class reference can refer to subclass objects
- If a subclass doesn’t implement all abstract methods, it must also be declared abstract
- You can have concrete methods in an abstract class
abstract means the class MUST be extended (inherited from).
final means the class CANNOT be extended.
These two keywords contradict each other, so they cannot be used together!
Exam Question 9: Consider the following code. What is wrong with it?
abstract class Shape {
abstract void draw();
}
class Circle extends Shape {
// No implementation of draw()
}
class Test {
public static void main(String[] args) {
Shape s = new Shape(); // Line A
}
}
Answer: There are TWO errors in this code:
Error 1 (Line A): You cannot instantiate an abstract class. “new Shape()” is invalid because Shape is abstract.
Error 2: The Circle class doesn’t implement the abstract method draw(). The Circle class must either:
- Implement the draw() method, OR
- Be declared abstract itself
Corrected code:
class Circle extends Shape {
void draw() { // Implement the abstract method
System.out.println("Drawing Circle");
}
}
// In main:
Shape s = new Circle(); // This is valid - using subclass object
10. Interfaces in Java
10.1 What is an Interface?
An interface in Java is a blueprint of a class. It contains only:
- Static constants
- Abstract methods (before Java 8)
Definition: An interface is a mechanism to achieve fully abstraction and multiple inheritance in Java.
Detailed Explanation:
Think of an interface like a contract or agreement. When a class implements an interface, it agrees to provide implementations for all the methods declared in that interface. The interface only declares WHAT methods should exist, not HOW they should work. The implementing class decides HOW to implement them.
10.2 Why Use Interfaces?
- Fully Abstraction: Interfaces provide 100% abstraction (all methods are abstract)
- Multiple Inheritance: A class can implement multiple interfaces
- Loose Coupling: Interfaces help create loosely coupled systems
- IS-A Relationship: Interfaces represent an IS-A relationship
10.3 Default Properties of Interface
The Java compiler automatically adds keywords to interface members:
| Member Type | Automatically Added Keywords |
|---|---|
| Interface fields | public, static, final |
| Interface methods | public, abstract |
This means all fields in an interface are constants, and all methods are abstract by default.
10.4 Syntax for Interface
interface InterfaceName {
// Constants (public static final by default)
int CONSTANT = 100;
// Abstract methods (public abstract by default)
void methodName();
}
10.5 Key Keywords for Interfaces
- A class extends another class
- A class implements an interface
- An interface extends another interface
+-----------+ +-------------+
| Class | extends | Class |
+-----------+ +-------------+
+-----------+ +-------------+
| Class | implements | Interface |
+-----------+ +-------------+
+-------------+ +-------------+
| Interface | extends | Interface |
+-------------+ +-------------+
10.6 Example: Basic Interface Implementation
// Interface definition
interface Printable {
void print(); // Abstract method
}
// Class implementing the interface
class Printed implements Printable {
// Must implement all abstract methods
public void print() {
System.out.println("Hello");
}
public static void main(String args[]) {
Printed p = new Printed();
p.print(); // Output: Hello
}
}
10.7 Multiple Inheritance Using Interfaces
Java doesn’t support multiple inheritance with classes, but it DOES support multiple inheritance using interfaces!
// Interface 1
interface Printable {
void print();
}
// Interface 2
interface Showable {
void show();
}
// Class implementing multiple interfaces
class Printed implements Printable, Showable {
// Must implement all methods from all interfaces
public void print() {
System.out.println("Hello");
}
public void show() {
System.out.println("Welcome");
}
public static void main(String args[]) {
Printed p = new Printed();
p.print(); // Output: Hello
p.show(); // Output: Welcome
}
}
10.8 Why Multiple Inheritance Works with Interfaces
Question: Why is multiple inheritance allowed with interfaces but not with classes?
Answer: With interfaces, there is no ambiguity because:
- Interfaces only declare methods, they don’t implement them
- The implementing class provides the implementation
- Even if two interfaces have the same method name, there’s only ONE implementation in the class
Example showing no ambiguity:
interface Printable {
void print(); // Same method name
}
interface Showable {
void print(); // Same method name
}
// No ambiguity - only one implementation needed
class TestInterface implements Printable, Showable {
public void print() {
System.out.println("Hello");
}
public static void main(String args[]) {
TestInterface t = new TestInterface();
t.print(); // Output: Hello (single implementation)
}
}
- An interface cannot be instantiated (just like abstract class)
- A class can implement MULTIPLE interfaces (separated by commas)
- All interface methods must be implemented by the class (unless the class is abstract)
- Interface methods are public and abstract by default
- Interface variables are public, static, and final by default
Exam Question 10: What is the difference between an abstract class and an interface?
Answer:
| Abstract Class | Interface |
|---|---|
| Can have both abstract and concrete methods | Only abstract methods (before Java 8) |
| Can have instance variables | Only constants (public static final) |
| Can have constructors | Cannot have constructors |
| A class can extend only ONE abstract class | A class can implement MULTIPLE interfaces |
| Can have any access modifier | Methods are public by default |
| Uses “extends” keyword | Uses “implements” keyword |
| Provides partial abstraction (0-100%) | Provides 100% abstraction |
11. UML Class Diagrams for Inheritance
Inheritance relationships are often shown graphically in UML (Unified Modeling Language) class diagrams.
11.1 UML Notation
- An arrow with an open arrowhead points from the child class to the parent class
- This represents the “IS-A” relationship
+-------------+
| Vehicle | <--- Superclass (Parent)
+-------------+
^
|
| (inheritance arrow - open arrowhead)
|
+-------------+
| Car | <--- Subclass (Child)
+-------------+
Interpretation: Car IS-A Vehicle
11.2 Example: Class Hierarchy
+-----------+
| Object | <-- Root of all classes
+-----+-----+
|
| extends
|
+-----+-----+
| Animal |
+-----+-----+
|
+-------------+-------------+
| | |
+-----+-----+ +-----+-----+ +-----+-----+
| Dog | | Cat | | Bird |
+-----------+ +-----------+ +-----------+
Exam Question 11: Draw a UML class diagram showing inheritance for the following: “ElectricCar” inherits from “Car” which inherits from “Vehicle”.
Answer:
+-------------+
| Vehicle | <--- Root superclass
+------+------+
|
| extends
|
+------v------+
| Car | <--- Middle class (subclass of Vehicle, superclass of ElectricCar)
+------+------+
|
| extends
|
+------v------+
| ElectricCar | <--- Leaf subclass
+-------------+
Key Points:
- Arrows point UPWARD (from child to parent)
- This represents multi-level inheritance
- ElectricCar inherits features from both Car AND Vehicle
12. Exam Tips
Important Tips for Your Exam:
- Know the Keywords:
extends– used for class inheritanceimplements– used for interfacesabstract– for abstract classes and methodssuper– to access parent class members
- Remember the Differences:
- Overloading vs Overriding
- Abstract class vs Interface
- Static binding vs Dynamic binding
- Compile-time polymorphism vs Runtime polymorphism
- Common Exam Traps:
- You CANNOT instantiate abstract classes or interfaces
- Multiple inheritance is NOT supported with classes (only interfaces)
- super() must be the FIRST statement in constructor
- Changing only return type is NOT valid overloading
- Code Output Questions:
- Trace polymorphic references carefully
- Check if methods are overridden correctly
- Verify abstract methods are implemented
- Diagram Drawing:
- Use open arrowheads pointing to parent class
- Label superclass and subclass clearly
13. Practice Questions
Practice Question 1: What will be the output of the following code?
class A {
void display() { System.out.print("A "); }
}
class B extends A {
void display() { System.out.print("B "); }
}
class C extends B {
void display() { System.out.print("C "); }
}
class Test {
public static void main(String[] args) {
A a = new C();
B b = new B();
a.display();
b.display();
}
}
Answer: Output is “B C”
Wait! Let me recalculate:
Actually the output is “C B”
Explanation:
A a = new C();– Reference type is A, object type is Ca.display();– Calls C’s display() (dynamic binding) → Output: “C “B b = new B();– Reference type is B, object type is Bb.display();– Calls B’s display() → Output: “B “
Final output: “C B”
Key Concept: In method overriding, the JVM determines which method to call based on the ACTUAL OBJECT TYPE, not the reference type. This is runtime polymorphism.
Practice Question 2: Identify and fix the error in the following code:
abstract class Shape {
abstract double area();
}
class Circle extends Shape {
double radius;
Circle(double r) { radius = r; }
}
class Test {
public static void main(String[] args) {
Shape s = new Circle(5.0);
System.out.println(s.area());
}
}
Answer: The error is that Circle class doesn’t implement the abstract method area() from Shape class.
Corrected code:
class Circle extends Shape {
double radius;
Circle(double r) { radius = r; }
// Must implement the abstract method
double area() {
return Math.PI * radius * radius;
}
}
Explanation: When a concrete class extends an abstract class, it MUST implement all abstract methods. Otherwise, the class itself must be declared abstract.
Practice Question 3: Can a class extend another class and implement an interface at the same time? If yes, write the syntax.
Answer: YES! A class can extend one class AND implement multiple interfaces.
Syntax:
class Child extends Parent implements Interface1, Interface2 {
// class body
}
Example:
class Animal { }
interface Flyable { void fly(); }
interface Swimmable { void swim(); }
class Duck extends Animal implements Flyable, Swimmable {
public void fly() { System.out.println("Duck flies"); }
public void swim() { System.out.println("Duck swims"); }
}
Key Point: The “extends” clause must come BEFORE the “implements” clause.
Practice Question 4: What is wrong with this interface definition?
interface Drawable {
private void draw();
protected int count = 0;
}
Answer: There are TWO errors:
Error 1: Interface methods are implicitly public. You cannot use “private” modifier. The compiler will give an error.
Error 2: Interface variables are implicitly public, static, and final. You cannot use “protected” modifier.
Corrected interface:
interface Drawable {
void draw(); // implicitly public abstract
int count = 0; // implicitly public static final
}
Remember: In interfaces, all methods are public and abstract by default, and all variables are public, static, and final by default. You cannot use more restrictive access modifiers.
Practice Question 5: Write a complete program that demonstrates:
- An abstract class “Shape” with abstract method “calculateArea()”
- Two subclasses “Rectangle” and “Circle” that extend Shape
- Use of super keyword to initialize dimensions
- Runtime polymorphism in the main method
Answer:
// Abstract class
abstract class Shape {
protected String name;
Shape(String name) {
this.name = name;
}
abstract double calculateArea();
void displayName() {
System.out.println("Shape: " + name);
}
}
// Subclass 1
class Rectangle extends Shape {
private double length;
private double width;
Rectangle(String name, double length, double width) {
super(name); // Call parent constructor
this.length = length;
this.width = width;
}
double calculateArea() {
return length * width;
}
}
// Subclass 2
class Circle extends Shape {
private double radius;
Circle(String name, double radius) {
super(name); // Call parent constructor
this.radius = radius;
}
double calculateArea() {
return Math.PI * radius * radius;
}
}
// Main class demonstrating runtime polymorphism
public class TestShape {
public static void main(String[] args) {
// Runtime polymorphism - Shape reference pointing to different objects
Shape s1 = new Rectangle("Rectangle1", 5, 3);
Shape s2 = new Circle("Circle1", 4);
s1.displayName();
System.out.println("Area: " + s1.calculateArea());
s2.displayName();
System.out.println("Area: " + s2.calculateArea());
}
}
Output:
Shape: Rectangle1 Area: 15.0 Shape: Circle1 Area: 50.26548245743669
14. Summary
Key Concepts Covered:
| Concept | Key Points |
|---|---|
| Inheritance | Mechanism where subclass acquires properties of superclass using “extends” keyword |
| Types of Inheritance | Single, Multiple (not in Java), Hierarchical, Multi-level, Hybrid, Multi-path |
| Method Overloading | Same name, different parameters in same class (compile-time polymorphism) |
| Method Overriding | Same name and parameters in subclass (runtime polymorphism) |
| Polymorphism | Many forms – Static (compile-time) and Dynamic (runtime) |
| super Keyword | Access parent class constructor and members |
| Abstract Class | Cannot be instantiated, may contain abstract methods |
| Interface | Blueprint of class, achieves full abstraction and multiple inheritance |
Congratulations! You have completed the chapter on Inheritance and Polymorphism. Make sure to practice the questions and review the key concepts before your exam. Good luck!