When would you use an interface, and when would you use an abstract class?

Interfaces and abstract classes are both used to achieve abstraction in Java, but they are designed for different scenarios. An interface is ideal for defining a contract that multiple classes can follow, while an abstract class is suitable when related classes need to share common state and behavior.

Key Points: • Use an interface when you want to define a common capability or contract for multiple unrelated classes. • Use an abstract class when you want to provide shared fields, common methods, and partial implementation. • A class can implement multiple interfaces but can extend only one abstract class. • Interfaces promote loose coupling and flexibility. • Abstract classes help avoid code duplication by providing reusable functionality.

When to Use an Interface:

Use an interface when different classes need to follow the same contract but may have completely different implementations.

Examples: • Payment systems (UPI, Credit Card, PayPal) • Notification services (Email, SMS, Push Notification) • Logging frameworks (File Logger, Database Logger)

Code Example:

interface Payment {

    void pay(double amount);
}

class UpiPayment implements Payment {

    @Override
    public void pay(double amount) {
        System.out.println("Paid using UPI");
    }
}

class CreditCardPayment implements Payment {

    @Override
    public void pay(double amount) {
        System.out.println("Paid using Credit Card");
    }
}

Here, different payment methods implement the same contract while providing their own implementations.

When to Use an Abstract Class:

Use an abstract class when related classes share common attributes and behavior.

Code Example:

abstract class Vehicle {

    void start() {
        System.out.println("Vehicle Started");
    }

    abstract void fuelType();
}

class Car extends Vehicle {

    @Override
    void fuelType() {
        System.out.println("Petrol");
    }
}

class ElectricCar extends Vehicle {

    @Override
    void fuelType() {
        System.out.println("Electric");
    }
}

Here, all vehicles share the start() method while providing their own fuelType() implementation.

Comparison:

Interface: • Defines a contract • No instance variables for object state • Supports multiple inheritance • Best for loose coupling

Abstract Class: • Provides shared implementation • Can contain fields and constructors • Supports single inheritance • Best for code reuse among related classes

Interview Tip: A concise interview answer is:

"Use an interface when multiple classes need to follow the same contract but may have different implementations. Use an abstract class when related classes share common state and behavior, and you want to provide partial implementation along with abstraction."