Bird
Raised Fist0

Interface vs Abstract Class - When Each Is the Right Choice

LLDmediumInterview freq: high
Choose your preparation mode4 modes available
🏗️
Interface vs Abstract Class - When Each Is the Right Choice
Understanding when to use Java interfaces versus abstract classes based on state, behavior, and extensibility needs.
mediumOOP Foundations for InterviewsFreq: high
Prerequisites:OOP FundamentalsJava Interfaces and Abstract ClassesJava Concurrency Basics
⚙️
Functional Requirements
  • Ability to declare methods without implementation (interface)
  • Ability to declare methods with default or abstract implementations (abstract class)
  • Support instance fields for shared state in abstract classes
  • Support multiple inheritance of type via interfaces
  • Support single inheritance of implementation via abstract classes
  • Ensure thread-safe method execution when accessing shared state
  • Allow extension without modifying existing classes (Open-Closed Principle)
👤
Use Cases
  • Define a contract for multiple implementations without shared state
  • Provide partial implementation with shared state and behavior
  • Extend existing code without modifying original classes
  • Ensure thread-safe access to shared mutable state
  • Demonstrate SOLID principles in design
  • Handle multiple concurrent threads accessing shared objects
🧑‍💻
Actors
  • Software Engineer
  • Code Reviewer
  • Interview Candidate
❓
Clarifying Questions to Ask
  • How many concurrent threads will access the shared objects?
  • Is shared mutable state required between implementations?
  • Should implementations be able to extend multiple types?
  • Are default method implementations needed?
  • What is the expected lifecycle of objects implementing these types?
  • Are there any performance constraints related to synchronization?
  • How should edge cases like partially initialized objects be handled?
Out of Scope
✗ Java 8+ default methods in interfaces (only basic interface vs abstract class)
✗ Full design of a specific domain system (focus is on pattern choice)
✗ Advanced concurrency utilities beyond synchronized and volatile
🔢
Enumerations
enum DesignChoice
INTERFACE | ABSTRACT_CLASS
Enumerates the two design options to prevent typo bugs and enable exhaustive switch statements when deciding pattern usage.
enum ConcurrencyMechanism
SYNCHRONIZED | VOLATILE | NONE
Enumerates concurrency control mechanisms to explicitly specify synchronization strategy and avoid ambiguity.
📦
TypeContract
2 fields
String nameDesignChoice designChoice
Represents the contract definition that can be realized as either an interface or an abstract class depending on designChoice.
public String getName()Returns the name of the contract.
public DesignChoice getDesignChoice()Returns whether the contract is an interface or abstract class.
📦
InterfaceType
2 fields
String nameList<String> methodSignatures
Defines a pure interface with method signatures only, no instance state.
public void addMethodSignature(String methodSignature)Adds a method signature to the interface.
public List<String> getMethodSignatures()Returns all method signatures declared in the interface.
📦
AbstractClassType
3 fields
String nameList<String> methodSignaturesMap<String, String> instanceFields
Defines an abstract class with method signatures and instance fields to hold shared state.
public void addMethodSignature(String methodSignature)Adds a method signature to the abstract class.
public void addInstanceField(String fieldType, String fieldName)Adds an instance field to the abstract class.
public Map<String, String> getInstanceFields()Returns all instance fields declared in the abstract class.
📦
ImplementationClass
4 fields
String nameTypeContract contractboolean extendsAbstractClassList<String> implementedMethods
Concrete class implementing either an interface or extending an abstract class, providing method implementations.
public void implementMethod(String methodSignature)Adds a method implementation to the class.
public boolean isExtendingAbstractClass()Returns true if the class extends an abstract class, false if it implements an interface.
📦
ConcurrencyControl
2 fields
ConcurrencyMechanism mechanismString rationale
Specifies the concurrency mechanism used to ensure thread safety in method execution.
public ConcurrencyMechanism getMechanism()Returns the concurrency mechanism used.
public String getRationale()Returns the rationale explaining why the concurrency mechanism is chosen.
🔗
Relationships
ImplementationClass──►TypeContract[1..1]
associationImplementationClass depends on TypeContract but contract can exist independently
AbstractClassType──►TypeContract[1..1]
inheritanceAbstractClassType is a specialized TypeContract
InterfaceType──►TypeContract[1..1]
inheritanceInterfaceType is a specialized TypeContract
ImplementationClass──►AbstractClassType[0..1]
inheritanceImplementationClass may extend AbstractClassType; AbstractClassType exists independently
ImplementationClass──►InterfaceType[0..*]
realizationImplementationClass may implement multiple InterfaceTypes; InterfaceTypes exist independently
ConcurrencyControl──►ImplementationClass[1..1]
associationConcurrencyControl is associated with ImplementationClass to specify thread safety strategy; both exist independently

Practice

(1/5)
1. In designing the Amazon Locker Service, should the Package entity be modeled as an abstract class or an interface, and why?
easy
A. Abstract class, because interfaces cannot have any methods related to package handling.
B. Abstract class, because Package has shared state like tracking info and common behavior.
C. Interface, because Package only defines behaviors and allows multiple inheritance of behavior.
D. Interface, because Package needs to hold mutable state for OTP and expiry.

Solution

  1. Step 1: Analyze Package state and behavior

    Package has shared mutable state such as OTP, expiry time, and tracking info, which requires fields and common method implementations.
  2. Step 2: Abstract class vs interface suitability

    Abstract classes can hold state and provide default behavior, interfaces cannot hold mutable state (prior to Java 8 default methods, but still no fields). Therefore, abstract class fits better.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Shared mutable state -> abstract class needed [check]
Hint: Stateful entities -> abstract class; stateless behaviors -> interface [check]
Common Mistakes:
2. In designing a collection class that supports iteration, should the iterator interface be an abstract class or an interface in Java, and why?
easy
A. Interface, because it enforces immutability of the collection during iteration.
B. Abstract class, because it allows sharing state and default implementation for iteration methods.
C. Abstract class, because Java interfaces cannot have methods with parameters.
D. Interface, because it defines behavior without state, allowing multiple implementations and better flexibility.

Solution

  1. Step 1: Understand Java interface vs abstract class

    Interfaces define behavior contracts without state, allowing multiple implementations. Abstract classes can hold state but restrict multiple inheritance.
  2. Step 2: Apply to iterator design

    Iterator interface defines traversal methods (e.g., hasNext(), next()) without state, enabling different iterator implementations per collection type.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Iterator as interface enables flexible, stateless traversal contracts [check]
Hint: Iterator interface defines behavior, no state needed [check]
Common Mistakes:
3. To add a WeekendFeeStrategy for pricing in the current product catalog design, which change respects SOLID principles with minimum modification?
medium
A. Create a new WeekendFeeStrategy class implementing FeeStrategy interface without changing existing classes
B. Modify the existing FeeStrategy class to add weekend logic with if-else
C. Add weekend fee logic inside ProductVariant class directly
D. Add a boolean flag isWeekend in PricingEngine and handle fees there

Solution

  1. Step 1: Identify applicable SOLID principle

    The Open-Closed Principle (OCP) requires that classes be open for extension but closed for modification.
  2. Step 2: Why creating a new class is best

    Implementing a new WeekendFeeStrategy class extends functionality without modifying existing code, preserving OCP and avoiding side effects.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    New strategy class -> OCP compliance, no existing class changes [check]
Hint: OCP: extend with new class, don't modify existing [check]
Common Mistakes:
4. The current parking lot design uses a FeeStrategy interface for pricing. To add a WeekendFeeStrategy without modifying existing classes, which SOLID principle is being applied and what is the minimum required change?
medium
A. Open-Closed Principle; create a new WeekendFeeStrategy class implementing FeeStrategy without changing existing code.
B. Dependency Inversion Principle; inject WeekendFeeStrategy into existing classes by changing their constructors.
C. Single Responsibility Principle; modify FeeStrategy interface to add weekend method.
D. Liskov Substitution Principle; override existing fee methods to handle weekends.

Solution

  1. Step 1: Identify the SOLID principle for extensibility

    Open-Closed Principle (OCP) states software entities should be open for extension but closed for modification.
  2. Step 2: Apply OCP by adding new strategy class

    Implement WeekendFeeStrategy as a new class implementing FeeStrategy interface, no changes to existing classes needed.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    New class implements interface -> existing code unchanged -> OCP [check]
Hint: Add new strategy class, no existing code change -> OCP [check]
Common Mistakes:
5. The Restaurant Management System needs to support ElectricCar vehicles that require ChargingSpots. What is the minimum change to the current Java design to add this feature without modifying existing classes?
hard
A. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility map externally.
B. Modify Vehicle class to include a boolean isElectric field and add charging logic inside existing methods.
C. Create a new ChargingSpot class extending Spot and modify TableManager to handle charging spots explicitly.
D. Add charging logic inside the existing Spot class and modify all subclasses to support electric vehicles.

Solution

  1. Step 1: Identify extensibility without modifying existing classes

    Adding new enum values and subclasses without changing existing classes respects OCP and avoids class explosion.
  2. Step 2: Update compatibility externally

    Updating SpotCompatibility map outside existing classes allows new vehicle and spot types to integrate without modifying existing code.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    New enums + subclass + external compatibility update -> minimal change [check]
Hint: Add enums + subclass + external map update -> minimal change [check]
Common Mistakes:
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard