← Back to Home

Module 2: Polymorphism and Interfaces

Module Overview

Explore polymorphism, interfaces, and how to use them effectively in Java.

Learning Objectives

Key Concepts

Polymorphism

Polymorphism is the ability to process objects differently based on their data type. It allows a single interface to represent different underlying types, enabling more flexible and reusable code.

Benefits of Polymorphism:

  • Code reusability and maintainability
  • Simplified method calls across different types
  • Runtime determination of which implementation to execute
  • Ability to extend functionality without modifying existing code

Example:

// Interface defining a contract
public interface Vehicle {
    void start();
    void stop();
    void accelerate();
}

// Implementation for a Car
public class Car implements Vehicle {
    @Override
    public void start() {
        System.out.println("Car engine starts with ignition key");
    }
    
    @Override
    public void stop() {
        System.out.println("Car stops by applying brakes");
    }
    
    @Override
    public void accelerate() {
        System.out.println("Car accelerates by pressing gas pedal");
    }
}

// Implementation for an Electric Bike
public class ElectricBike implements Vehicle {
    @Override
    public void start() {
        System.out.println("Electric bike starts with power button");
    }
    
    @Override
    public void stop() {
        System.out.println("Bike stops by applying brakes");
    }
    
    @Override
    public void accelerate() {
        System.out.println("Bike accelerates by twisting throttle");
    }
}

// Using polymorphism
public class VehicleTest {
    public static void main(String[] args) {
        // Vehicle reference can hold different implementations
        Vehicle myCar = new Car();
        Vehicle myBike = new ElectricBike();
        
        // Same method calls, different behaviors
        myCar.start();    // "Car engine starts with ignition key"
        myBike.start();   // "Electric bike starts with power button"
    }
}

Interfaces

An interface is a contract that defines what a class can do without specifying how it does it. Interfaces contain method signatures without implementations and can include constant values.

Characteristics of Interfaces:

  • Define methods without implementation (abstract by default)
  • Cannot be instantiated directly
  • Classes can implement multiple interfaces
  • All fields in interfaces are implicitly public, static, and final

Example:

// Interface definition
public interface Sortable {
    // Constants (implicitly public, static, final)
    int ASCENDING = 1;
    int DESCENDING = -1;
    
    // Abstract methods (no implementation)
    void sort(int direction);
    boolean isSorted();
}

// Class implementing the interface
public class SortableArray implements Sortable {
    private int[] data;
    
    public SortableArray(int[] data) {
        this.data = data;
    }
    
    @Override
    public void sort(int direction) {
        // Implementation of sorting algorithm
        if (direction == ASCENDING) {
            // Sort in ascending order
        } else {
            // Sort in descending order
        }
    }
    
    @Override
    public boolean isSorted() {
        // Implementation to check if array is sorted
        return true; // Placeholder
    }
}

"Is-a" vs "Has-a" Relationships

In object-oriented programming, understanding the relationships between classes is crucial:

"Is-a" Relationship (Inheritance/Implementation):

  • Established through class inheritance or interface implementation
  • Example: A Car "is-a" Vehicle, a Circle "is-a" Shape
  • Represented by extends or implements keywords

"Has-a" Relationship (Composition):

  • Established when one class contains an instance of another class
  • Example: A Car "has-a" Engine, a Library "has-a" collection of Books
  • Implemented by declaring member variables

Example:

// "Is-a" relationship example
public interface Shape {
    double area();
    double perimeter();
}

public class Circle implements Shape {  // Circle "is-a" Shape
    private double radius;
    
    public Circle(double radius) {
        this.radius = radius;
    }
    
    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
    
    @Override
    public double perimeter() {
        return 2 * Math.PI * radius;
    }
}

// "Has-a" relationship example
public class Car {
    private Engine engine;  // Car "has-a" Engine
    private Wheel[] wheels;
    
    public Car() {
        engine = new Engine();
        wheels = new Wheel[4];
        for (int i = 0; i < 4; i++) {
            wheels[i] = new Wheel();
        }
    }
    
    public void start() {
        engine.turnOn();
    }
}

Resources