Object Oriented Programming with JavaUnit 511 min read
Interfaces, Abstract Classes & Polymorphism in Java
Unit 5 of Object Oriented Programming with Java covers interfaces (contracts, multiple inheritance, default/static methods), abstract classes (partial implementation, abstract methods), and their real-world applications in designing flexible, reusable code. Learn how to use them to enforce structure, achieve polymorphi
TAKEAWAYS:
- Interfaces define what a class can do (methods) without specifying how, enabling multiple inheritance of type.
- Abstract classes provide partial implementation (fields + some methods) and enforce is-a relationships via
abstractmethods. - Default methods in interfaces allow adding new functionality without breaking existing implementations.
- Polymorphism via interfaces/abstract classes lets you write code that works with any implementing class (e.g.,
List<String>forArrayListorLinkedList). - Key difference: Interfaces are for capability ("can fly"), abstract classes for inheritance ("is a vehicle").
- Real-world use: APIs (e.g.,
Comparable,Serializable), frameworks (Spring’s@Transactional), and design patterns (Strategy, Observer).
1. Interfaces: Contracts for Behavior
An interface is a reference type that defines a set of methods a class must implement, but provides no implementation itself. It enforces a contract that classes must follow.
Syntax and Key Features
public interface Flyable {
// Abstract method (implicitly public abstract)
void fly();
// Default method (Java 8+)
default void land() {
System.out.println("Landing...");
}
// Static method (Java 8+)
static void takeOff() {
System.out.println("Preparing for takeoff.");
}
}
- All methods are
public abstractby default (no access modifiers orabstractkeyword needed). - Default methods allow adding new methods without breaking existing implementations.
- Static methods provide utility functions tied to the interface (e.g.,
Collections.sort()usesComparable).
Why Use Interfaces?
| Feature | Interface | Abstract Class |
|---|---|---|
| Inheritance | Multiple (class A implements X, Y) |
Single (class A extends B) |
| Fields | Only public static final (constants) |
Can have instance variables |
| Constructors | No constructors | Can have constructors |
| Purpose | "Can do" (e.g., Runnable, Serializable) |
"Is a" (e.g., AbstractList) |
Example: Comparable Interface
public class Student implements Comparable<Student> {
private String name;
private int rollNo;
@Override
public int compareTo(Student other) {
return this.rollNo - other.rollNo; // Sort by roll number
}
}
Use Case: Sorting a list of Student objects:
List<Student> students = new ArrayList<>();
students.sort(null); // Uses Comparable.compareTo()
2. Implementing Interfaces
A class implements an interface using the implements keyword and provides concrete implementations for all abstract methods.
Example: Flyable Interface
public class Bird implements Flyable {
@Override
public void fly() {
System.out.println("Bird is flying with wings.");
}
}
public class Drone implements Flyable {
@Override
public void fly() {
System.out.println("Drone is flying with propellers.");
}
}
Polymorphism in Action:
Flyable[] flyers = {new Bird(), new Drone()};
for (Flyable flyer : flyers) {
flyer.fly(); // Calls the correct implementation
}
Output:
Bird is flying with wings.
Drone is flying with propellers.
MERMAID FLOWCHART:
flowchart TD
A["Flyable interface"] -->|"implements"| B["Bird class"]
A -->|"implements"| C["Drone class"]
B -->|"fly()"| D["Prints: Bird is flying..."]
C -->|"fly()"| E["Prints: Drone is flying..."]
F["Flyable[] flyers"] -->|"polymorphic call"| D
F -->|"polymorphic call"| E3. Default and Static Methods
Default Methods
- Allow adding new methods to interfaces without breaking existing implementations.
- Use the
defaultkeyword and provide a body.
Example: Adding land() to Flyable:
public interface Flyable {
void fly();
default void land() {
System.out.println("Landing safely.");
}
}
Conflict Resolution: If a class implements two interfaces with the same default method, it must override it.
public class Parrot implements Flyable, Swimmable {
@Override
public void land() {
System.out.println("Parrot lands on a branch.");
}
}
Static Methods
- Belong to the interface itself, not instances.
- Called using the interface name (e.g.,
Flyable.takeOff()).
Example: takeOff() in Flyable:
public interface Flyable {
static void takeOff() {
System.out.println("Preparing for takeoff...");
}
}
Flyable.takeOff(); // Output: Preparing for takeoff...
MERMAID STATE DIAGRAM:
4. Abstract Classes: Partial Implementation
An abstract class is a class that cannot be instantiated and may contain abstract methods (no body) and concrete methods (with body). It provides a partial implementation.
Syntax
public abstract class Vehicle {
private String model;
public Vehicle(String model) {
this.model = model;
}
// Abstract method (no body)
public abstract void start();
// Concrete method (with body)
public void displayModel() {
System.out.println("Model: " + model);
}
}
Key Points:
- Can have constructors, fields, and methods with bodies.
- Cannot be instantiated (
new Vehicle()is invalid). - Used for shared code among related classes (e.g.,
Animal→Dog,Cat).
Example: Vehicle Hierarchy
public class Car extends Vehicle {
public Car(String model) {
super(model);
}
```figure
{"type":"tree","root":{"v":"Vehicle (Abstract)","children":[{"v":"Car","children":[{"v":"ElectricCar"}]},{"v":"Truck"}]},"caption":"Inheritance hierarchy showing abstract base class and concrete subclasses"}
@Override
public void start() {
System.out.println("Car engine started.");
}
}
public class Bike extends Vehicle { public Bike(String model) { super(model); }
@Override
public void start() {
System.out.println("Bike kick-started.");
}
}
**Usage**:
```java
Vehicle car = new Car("Toyota");
car.start(); // Output: Car engine started.
car.displayModel(); // Output: Model: Toyota
5. Interfaces vs. Abstract Classes: When to Use Which
| Scenario | Use Interface | Use Abstract Class |
|---|---|---|
| Multiple inheritance needed | ✅ (e.g., class Bat implements Flyable, Swimmable) |
❌ (Java doesn’t support multiple inheritance) |
| Defining a capability | ✅ (e.g., Runnable, Comparable) |
❌ |
| Shared code among subclasses | ❌ | ✅ (e.g., AbstractList in Java Collections) |
| Non-instantiable base class | ❌ (unless all methods are abstract) | ✅ (e.g., AbstractMap) |
| Default behavior for new methods | ✅ (default methods) | ❌ |
MERMAID DECISION TREE:
flowchart TD
A["Need multiple inheritance?"] -->|"Yes"| B["Use Interface"]
A -->|"No"| C["Shared code needed?"]
C -->|"Yes"| D["Use Abstract Class"]
C -->|"No"| E["Defining a capability?"]
E -->|"Yes"| B
E -->|"No"| F["Non-instantiable base?"]
F -->|"Yes"| D
F -->|"No"| G["Use Interface or Class"]6. Real-World Applications
In the Real World
Khalti Payment System
- Uses interfaces like
PaymentGatewayto support multiple payment methods (e.g.,CreditCardPayment,MobileWalletPayment). - How: The
PaymentProcessorclass depends onPaymentGateway, allowing new payment methods (e.g.,UPI) without modifying existing code.
- Uses interfaces like
Pathao Driver App
- Implements
LocationUpdaterinterface for GPS tracking. - How: Different transport modes (
Bike,Car,Auto) implementLocationUpdater.updateLocation()to send real-time coordinates to the server.
- Implements
Nepal Stock Exchange (NEPSE)
- Uses
TradingStrategyinterface for algorithmic trading. - How: Strategies like
MovingAverageStrategyorVolumeWeightedStrategyimplementexecuteTrade()without coupling to a specific exchange.
- Uses
WORKED EXAMPLE: NTC Traffic Route Optimization Assume NTC uses interfaces to manage traffic routes dynamically:
public interface TrafficRoute {
void optimizeRoute();
}
public class HighwayRoute implements TrafficRoute {
@Override
public void optimizeRoute() {
System.out.println("Optimizing via highways (fastest).");
}
}
public class LocalRoute implements TrafficRoute {
@Override
public void optimizeRoute() {
System.out.println("Optimizing via local roads (less traffic).");
}
}
Usage in NTC System:
TrafficRoute route = new LocalRoute(); // Depends on traffic conditions
route.optimizeRoute(); // Output: Optimizing via local roads...
Visualization:
flowchart TD
A["NTC Traffic System"] -->|"uses"| B["TrafficRoute interface"]
B -->|"implemented by"| C["HighwayRoute"]
B -->|"implemented by"| D["LocalRoute"]
A -->|"calls"| C
A -->|"calls"| D7. Exam Tip
Interface vs. Abstract Class:
- Exam loves: Asking you to choose between the two for a given scenario. Remember:
- Can a class extend multiple abstract classes? → No (Java doesn’t support multiple inheritance).
- Can a class implement multiple interfaces? → Yes.
- Common Pitfall: Forgetting to implement all abstract methods in a class.
- Exam loves: Asking you to choose between the two for a given scenario. Remember:
Default Method Conflicts:
- If two interfaces have the same default method, the implementing class must override it. This is a frequent exam question.
Polymorphism:
- Always test your code with polymorphism. For example:
List<String> list = new ArrayList<>(); // Polymorphism: List interface, ArrayList implementation - Exam Question: Given a hierarchy, write code to demonstrate polymorphism.
- Always test your code with polymorphism. For example:
Abstract Methods:
- An abstract class can have abstract methods, but does not have to. If it has at least one abstract method, it must be declared
abstract.
- An abstract class can have abstract methods, but does not have to. If it has at least one abstract method, it must be declared
Static Methods in Interfaces:
- Can be called without an instance (e.g.,
Collections.sort()usesComparable’s static utility methods).
- Can be called without an instance (e.g.,
PRACTICE QUESTION:
interface A {
void show();
default void display() { System.out.println("A"); }
}
interface B extends A {
void show();
default void display() { System.out.println("B"); }
}
class C implements B {
public void show() { System.out.println("C"); }
// No override for display() → Compile-time error!
}
Why does this fail?
- Answer: Class
CimplementsB, which extendsA. BothAandBhave a default methoddisplay(). SinceCdoes not overridedisplay(), the compiler cannot decide which default method to use. Always override default methods in conflicts.
MERMAID ERROR FLOW:
flowchart TD
A["Class C implements B"] --> B["B extends A"]
B --> C["A has default display()"]
B --> D["B has default display()"]
D --> E["Conflict: No override in C"]
E --> F["Compile-time Error"]Based on the TU BIM syllabus for Object Oriented Programming with Java (IT234), unit 5.
Discussion
Loading…