DEV Community

Rajesh Bhola
Rajesh Bhola

Posted on

Part 5 - Interface vs Abstract Class vs Concrete Class

In the previous articles, we learned what interfaces are, how they work, and why they are fundamental to Java programming.

However, one question still remains:

When should we use an Interface, an Abstract Class, or a Concrete Class?

This is one of the most frequently asked Java interview questions because choosing the right abstraction directly affects the design, flexibility, and maintainability of your application.

In this article, we'll compare these three concepts in depth with practical examples and interview-oriented explanations.


Why Do We Need Different Types of Classes?

Not every Java class serves the same purpose.

Sometimes, you only know what should be done but not how.

Sometimes, you already have some common implementation.

Sometimes, everything is fully implemented and ready to use.

Java provides three different constructs for these situations:

  • Interface
  • Abstract Class
  • Concrete Class

Choosing the right one helps build clean, reusable, and maintainable software.


When Should You Use an Interface?

Use an interface when you only know the requirement or contract, but not the implementation.

In other words, an interface defines what a class should do, not how it should do it.

Example:

interface PaymentService {

    void processPayment();

}
Enter fullscreen mode Exit fullscreen mode

The interface does not care whether the payment is processed using:

  • Credit Card
  • UPI
  • Net Banking
  • PayPal

Each implementation class decides that.


Step-by-Step Explanation

Step 1

The interface defines the required service.

Step 2

No implementation is provided.

Step 3

Implementation classes decide how to perform the task.

Step 4

Clients use the interface without depending on a specific implementation.


When Should You Use an Abstract Class?

Use an abstract class when you already know part of the implementation, but some behavior still depends on child classes.

Example:

abstract class PaymentService {

    public void validatePayment() {

        System.out.println("Validating payment...");

    }

    public abstract void processPayment();

}
Enter fullscreen mode Exit fullscreen mode

Here:

  • Validation logic is common.
  • Payment processing differs for each payment type.

Step-by-Step Explanation

Step 1

The abstract class provides common code.

Step 2

Some methods remain abstract.

Step 3

Child classes inherit common functionality.

Step 4

Each child implements only the missing behavior.


When Should You Use a Concrete Class?

Use a concrete class when everything is fully implemented and ready for use.

Example:

class CreditCardPaymentService {

    public void processPayment() {

        System.out.println("Payment completed.");

    }

}
Enter fullscreen mode Exit fullscreen mode

The class is complete.

Objects can be created immediately.


Quick Decision Table

Situation Use
Only requirement specification Interface
Partial implementation Abstract Class
Complete implementation Concrete Class

Interface vs Abstract Class

Let's compare them feature by feature.


1. Purpose

Interface Abstract Class
Defines a contract Provides partial implementation

2. Methods

Traditionally, interface methods are abstract.

interface PaymentService {

    void processPayment();

}
Enter fullscreen mode Exit fullscreen mode

Abstract classes may contain both abstract and concrete methods.

abstract class PaymentService {

    abstract void processPayment();

    void validatePayment() {

    }

}
Enter fullscreen mode Exit fullscreen mode

Modern Java Note: Since Java 8, interfaces can also contain default and static methods, and since Java 9, private helper methods. This article focuses on the traditional interview concepts while acknowledging these modern additions.


3. Variables

Interface variables are always constants.

interface AppConstants {

    int MAX_USERS = 100;

}
Enter fullscreen mode Exit fullscreen mode

The compiler treats it as:

public static final int MAX_USERS = 100;
Enter fullscreen mode Exit fullscreen mode

Abstract classes can contain:

  • Instance variables
  • Static variables
  • Final variables

Example:

abstract class Employee {

    protected String employeeName;

    protected int employeeId;

}
Enter fullscreen mode Exit fullscreen mode

4. Constructors

Interfaces do not define constructors because they are not instantiated.

Abstract classes can define constructors.

Example:

abstract class Employee {

    Employee() {

        System.out.println("Employee initialized.");

    }

}
Enter fullscreen mode Exit fullscreen mode

When a child object is created, the abstract class constructor executes automatically.


5. Initialization Blocks

Interfaces cannot contain:

  • Instance initialization blocks

Abstract classes can.

Example:

abstract class Employee {

    {

        System.out.println("Instance block");

    }

}
Enter fullscreen mode Exit fullscreen mode

6. Object Creation

Interfaces:

PaymentService service = new PaymentService();
Enter fullscreen mode Exit fullscreen mode

Compile-Time Error

PaymentService is abstract; cannot be instantiated
Enter fullscreen mode Exit fullscreen mode

Abstract classes:

abstract class PaymentService {

}
Enter fullscreen mode Exit fullscreen mode
PaymentService service = new PaymentService();
Enter fullscreen mode Exit fullscreen mode

Compile-Time Error

PaymentService is abstract; cannot be instantiated
Enter fullscreen mode Exit fullscreen mode

Concrete classes:

class CreditCardPaymentService {

}
Enter fullscreen mode Exit fullscreen mode
CreditCardPaymentService service =
        new CreditCardPaymentService();
Enter fullscreen mode Exit fullscreen mode

Works successfully.


Complete Comparison Table

Feature Interface Abstract Class Concrete Class
Object Creation ❌ No ❌ No ✅ Yes
Constructors ❌ No ✅ Yes ✅ Yes
Instance Variables ❌ No ✅ Yes ✅ Yes
Static Variables ✅ Yes ✅ Yes ✅ Yes
Abstract Methods ✅ Yes ✅ Yes ❌ No
Concrete Methods ✅ Yes (default/static methods in modern Java) ✅ Yes ✅ Yes
Multiple Inheritance ✅ Supported ❌ Not Supported ❌ Not Supported
Primary Purpose Contract Partial implementation Complete implementation

Real-World Example

Suppose you're building an online shopping application.

Interface

interface PaymentService {

    void processPayment();

}
Enter fullscreen mode Exit fullscreen mode

Abstract Class

abstract class BasePaymentService
        implements PaymentService {

    public void validate() {

        System.out.println("Validation completed.");

    }

}
Enter fullscreen mode Exit fullscreen mode

Concrete Class

class CreditCardPaymentService
        extends BasePaymentService {

    @Override
    public void processPayment() {

        System.out.println("Credit Card Payment.");

    }

}
Enter fullscreen mode Exit fullscreen mode

ASCII Diagram

          PaymentService
             (Interface)
                  │
                  ▼
      BasePaymentService
        (Abstract Class)
                  │
                  ▼
   CreditCardPaymentService
        (Concrete Class)
Enter fullscreen mode Exit fullscreen mode

Common Beginner Mistakes

Mistake 1: Using an Abstract Class When Only a Contract Is Needed

If there is no shared implementation, prefer an interface.


Mistake 2: Putting Business Logic Inside an Interface

Interfaces should define contracts.

Complex implementation belongs in classes.


Mistake 3: Making Every Class Abstract

Only use an abstract class when you genuinely want to prevent direct instantiation and share common implementation.


Mistake 4: Forgetting That Abstract Classes Can Have Constructors

Many beginners incorrectly assume abstract classes cannot have constructors.

They absolutely can.


Best Practices

  • Prefer interfaces when multiple implementations are expected.
  • Use abstract classes for shared code and common state.
  • Keep concrete classes focused on business logic.
  • Design around interfaces to reduce coupling.
  • Follow the SOLID principles, especially the Dependency Inversion Principle (DIP).

Interview Questions

1. When should you use an interface?

When only the contract is known and multiple implementations are expected.

Why interviewers ask

To evaluate your understanding of abstraction and API design.


2. When should you use an abstract class?

When multiple classes share common state or behavior, but some methods still require implementation by subclasses.


3. Can an abstract class have a constructor?

Yes.

It is executed whenever a child class object is created.


4. Can we create an object of an interface?

No.

Interfaces cannot be instantiated.


5. Can we create an object of an abstract class?

No.

Only its subclasses can be instantiated.


6. Why can interfaces support multiple inheritance but classes cannot?

Interfaces primarily define contracts, avoiding the ambiguity caused by inheriting multiple implementations.


7. Which is better: Interface or Abstract Class?

Neither is universally better.

Choose based on the problem:

  • Interface → Contract and flexibility
  • Abstract Class → Shared implementation
  • Concrete Class → Complete implementation

Common trap

Saying "always use interfaces" or "abstract classes are outdated." The correct choice depends on your design requirements.


Quick Memory Trick 🧠

Remember IPC:

Interface
      │
      ▼
Requirement (Contract)

Abstract Class
      │
      ▼
Partial Implementation

Concrete Class
      │
      ▼
Complete Implementation
Enter fullscreen mode Exit fullscreen mode

Think IPC whenever you need to decide which one to use.


Key Takeaways

  • Use an interface when defining a contract.
  • Use an abstract class for partial implementation and shared state.
  • Use a concrete class when the implementation is complete.
  • Interfaces focus on what should be done.
  • Abstract classes combine what and how.
  • Concrete classes provide the final implementation.
  • Abstract classes can have constructors and instance variables.
  • Interfaces enable multiple inheritance of type, while classes do not support multiple inheritance.

If you found this guide helpful, leave a ❤️ and follow for more beginner-friendly Java tutorials, interview questions, and practical coding examples.

Happy Coding!

Top comments (0)