Back to Abstraction & Interfaces
Q4Question 4 of 4

When do you choose interface vs abstract class?

Key Concepts
  • Choose interface when defining a capability contract that unrelated classes can implement (Auditable, Comparable)
  • Choose abstract class when sharing mutable state (fields) and constructors among a family of related classes
  • Java 8 default methods narrowed the gap but interfaces still cannot have constructors or instance fields
  • Interface default methods are implicitly public: no protected access for family-only methods
  • A class can extend only one abstract class but implement unlimited interfaces
  • Modern guideline: default to interface; use abstract class only when you need constructors or shared mutable state

Definition

Interface for capability contracts (multiple inheritance, no state). Abstract class for family hierarchies (shared state, constructors). Java 8 default methods help but still no constructors, no instance fields, no protected methods.

The choice between interface and abstract class depends on four remaining differences after Java 8.

  • Choose interface when: defining a capability contract that unrelated classes can implement (Auditable, Comparable, Serializable), you need multiple inheritance of type, or the contract has no mutable state.
  • Choose abstract class when: sharing mutable state (fields) and constructors among a family of related classes (SavingsAccount and CurrentAccount share balance, accountId), or you need non-public methods (protected helper methods).
  • Why not interchangeable: (1) interfaces cannot have constructors, (2) interfaces cannot have instance fields, (3) interface methods are implicitly public (no protected), (4) a class can extend only one abstract class.
  • Modern guideline: default to interface. Use abstract class only when you need constructors or shared mutable instance fields.

Interface is like a banking license at National Bank of India: any institution (bank, fintech, cooperative) can hold it. Multiple licenses allowed. Abstract class is like a bank template with pre-filled forms and a vault (state): only branches of this bank can use it. You can only belong to one bank (single inheritance) but hold many licenses (multiple interfaces). Java 8 gave licenses the ability to include instructions (default methods), but licenses still cannot have a vault (state) or a reception desk (constructor).

Understanding the Concepts

When do you choose interface vs abstract class?

The decision is driven by four remaining differences after Java 8.

What are the four remaining differences?

JAVA
// Difference 1: CONSTRUCTORS
public abstract class Account {
    protected Account(String accountId, java.math.BigDecimal balance) {
        // Constructor initializes shared state for all subclasses.
    }
}
// Interface: no constructor. Cannot initialize state on creation.

// Difference 2: INSTANCE FIELDS
public abstract class Account {
    protected java.math.BigDecimal balance; // mutable instance field
}
public interface Auditable {
    java.math.BigDecimal MAX = java.math.BigDecimal.TEN; // public static final only
    // BigDecimal balance; -> compile error: no instance fields
}

// Difference 3: ACCESS MODIFIERS
public abstract class Account {
    protected void internalValidate() { } // protected: family only
}
public interface Auditable {
    void generateReport(); // implicitly public
    // protected void internal() { } -> compile error
}

// Difference 4: SINGLE vs MULTIPLE INHERITANCE
class SavingsAccount extends Account implements Auditable, Taxable { }
// class X extends Account, AnotherClass { } -> compile error

What is the decision flowchart?

Step 1: Do you need instance fields (mutable state shared across subclasses)? Yes -> abstract class.
Step 2: Do you need a constructor to initialize state? Yes -> abstract class.
Step 3: Do multiple unrelated classes need this capability? Yes -> interface.
Step 4: Is this a family of related classes (IS-A hierarchy)? Yes -> abstract class.
Step 5: When in doubt -> interface. Use abstract class only when you need constructors or shared mutable state.

What does this look like in a real banking system?

JAVA
// Account: abstract class (has state, constructor, template method)
public abstract class Account {
    protected java.math.BigDecimal balance;
    private final String accountId;
    protected Account(String id, java.math.BigDecimal bal) {
        this.accountId = id; this.balance = bal;
    }
    public abstract java.math.BigDecimal calculateInterest();
}

// Auditable: interface (capability, any class can have it)
public interface Auditable {
    java.util.List<String> generateAuditReport();
}

// Taxable: interface (capability, any class can have it)
public interface Taxable {
    java.math.BigDecimal calculateTax();
}

// SavingsAccount: extends abstract class, implements interfaces
public class SavingsAccount extends Account implements Auditable, Taxable {
    // Account: shared state (balance, accountId) + template method
    // Auditable + Taxable: capabilities from interfaces
}

What does Spring use in practice?

JAVA
// Spring uses interfaces for contracts:
public interface JpaRepository<T, ID> { } // any entity can implement
public interface Serializable { }           // any class can implement

// Spring uses abstract classes for shared state and template methods:
public abstract class AbstractController {
    private WebApplicationContext context; // state: interface cannot have this
    protected abstract ModelAndView handleRequest();
}

How do interface and abstract class compare?

| Aspect | Interface | Abstract Class |
|--------|----------|----------------|
| Instance fields | No (constants only) | Yes |
| Constructors | No | Yes |
| Multiple inheritance | Yes | No |
| Access modifiers | public only | Any |
| Default methods (Java 8) | Yes | N/A (always had bodies) |
| Use case | Capability contract | Family with shared state |

What are common mistakes?

The most common mistake is using an abstract class for a stateless contract, wasting the single inheritance slot.

What should a senior engineer know?

  • In Spring Boot, services implement interfaces (loose coupling, multiple implementations). JPA entity base classes are abstract classes (shared @Id, @CreatedDate fields).
  • The choice is driven by state: if you need shared mutable state with initialization, abstract class. If you need a contract with optional default behavior, interface.
  • Sealed interfaces (Java 17) combine interface flexibility with controlled hierarchy.

Visual Overview

DIAGRAM
  DECISION FLOWCHART
  ──────────────────────────────────────────
  Need instance fields? ──Yes──> ABSTRACT CLASS
         │
         No
         │
  Need constructor? ──Yes──> ABSTRACT CLASS
         │
         No
         │
  Multiple unrelated classes? ──Yes──> INTERFACE
         │
         No
         │
  Family IS-A hierarchy? ──Yes──> ABSTRACT CLASS
         │
         No
         │
  Default choice ──────────────> INTERFACE

Key Takeaway

Choose interface when defining a capability that unrelated classes can implement (Auditable, Comparable, Serializable) and you need multiple inheritance of type. Choose abstract class when sharing mutable state (balance field, auditLog list) and constructors among a family of related classes (SavingsAccount IS-A Account). Java 8 default methods narrowed the gap by adding method bodies to interfaces, but they are still not interchangeable.

The four remaining differences: interfaces cannot have instance fields (only public static final constants), cannot have constructors (no state initialization), default methods are implicitly public (no protected access for family-only methods), and a class can extend only one abstract class but implement unlimited interfaces.

Remember one sentence: default to interface for contracts and capabilities, and use abstract class only when you genuinely need constructors or shared mutable instance fields.

---

Share
Use ← → arrow keys to navigate