Bird
Raised Fist0

Interface vs Abstract Class - When Each Is the Right Choice

LLDmediumInterview freq: high
Choose your preparation mode4 modes available
▶
Class Trace
Step 1/4
TypeContract and InterfaceType realization

TypeContract is a pure interface defining a contract with no state, InterfaceType extends it as another interface to add behavior.

🎯 Tests whether candidate knows interfaces cannot hold instance state in Java and are used for behavior abstraction only.
public interface TypeContract {
    void execute();
}

public interface InterfaceType extends TypeContract {
    void methodA();
}
ImplementationClass realizes InterfaceType

ImplementationClass provides concrete behavior for InterfaceType methods, demonstrating realization of interfaces.

🎯 Tests candidate's understanding of interface realization and how concrete classes implement interface contracts.
public class ImplementationClass implements InterfaceType {
    @Override
    public void execute() {
        // implementation
    }
    @Override
    public void methodA() {
        // implementation
    }
}
AbstractClassType with volatile state and synchronized init()

AbstractClassType holds volatile boolean isInitialized and synchronized init() method to safely publish state across threads.

🎯 Tests candidate's knowledge that abstract classes can hold instance state and use volatile and synchronized for thread-safe state initialization.
public abstract class AbstractClassType {
    protected volatile boolean isInitialized = false;
    public synchronized void init() {
        if (!isInitialized) {
            // initialization logic
            isInitialized = true;
        }
    }
}
ConcurrencyControl extends AbstractClassType with synchronized lock()

ConcurrencyControl extends AbstractClassType and adds synchronized lock() and unlock() methods to control concurrent access.

🎯 Tests candidate's understanding of inheritance to extend abstract class behavior and use of synchronized methods for concurrency control.
public class ConcurrencyControl extends AbstractClassType {
    public synchronized void lock() {
        // locking logic
    }
    public void unlock() {
        // unlocking logic
    }
}
📐
Class Diagram
Class Diagram
       +----------------+
       | <<Interface>>  |
       | TypeContract   |
       +----------------+
       | +void execute()|
       +----------------+
              |
              | --► realization
              |
       +---------------------+
       | <<Interface>>       |
       | InterfaceType       |
       +---------------------+
       | +void methodA()     |
       +---------------------+
              |
              | --► realization
              |
       +---------------------+
       | ImplementationClass |
       +---------------------+
       | +void methodA()     |
       +---------------------+
 
       +---------------------+
       | <<Abstract>>        |
       | AbstractClassType   |
       +---------------------+
       | -volatile boolean   |
       |   isInitialized     |
       | +synchronized void  |
       |   init() [sync]     |
       +---------------------+
              ^
              | extends
       +---------------------+
       | ConcurrencyControl   |
       +---------------------+
       | +void lock() [sync] |
       | +void unlock()      |
       +---------------------+

This diagram illustrates key Java OOP design decisions for choosing interfaces versus abstract classes. TypeContract and InterfaceType are interfaces representing pure behavior abstraction without state, enforcing the Open-Closed Principle by allowing new implementations without modification. ImplementationClass realizes InterfaceType, showing concrete behavior implementation. AbstractClassType is an abstract class holding volatile instance state and synchronized methods, demonstrating why abstract classes are chosen when shared state and thread-safe initialization are required. ConcurrencyControl extends AbstractClassType to add synchronized concurrency control methods, illustrating inheritance to extend behavior safely. The use of volatile and synchronized keywords ensures safe publication and atomicity in multithreaded contexts, a critical Java-specific concurrency mechanism. Relationships show realization for interfaces and inheritance for abstract class extension, clarifying lifecycle and extensibility.

Primary Focus

✓ Abstract class state vs interface behavior + Realization vs Inheritance + Composition lifecycle + Volatile singleton concurrency

Practice

(1/5)
1. In a notification system, a NotificationFactory class has a static method that returns different Notification subclasses (e.g., EmailNotification, SMSNotification) based on input parameters. Which design pattern is applied here and why is it the correct choice?
easy
A. Builder pattern, because it constructs complex notification objects step-by-step.
B. Factory pattern, because it encapsulates object creation and returns subclasses based on input.
C. Singleton pattern, because it ensures only one factory instance exists.
D. Decorator pattern, because it adds responsibilities to notifications dynamically.

Solution

  1. Step 1: Identify the role of NotificationFactory

    The factory method returns different Notification subclasses based on input parameters, encapsulating object creation logic.
  2. Step 2: Eliminate other patterns

    Builder is for stepwise construction, Singleton ensures single instance, Decorator adds behavior dynamically; none match the described creation logic.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Factory pattern encapsulates subclass instantiation based on input [check]
Hint: Factory creates objects based on input type [check]
Common Mistakes:
2. In a Snake and Ladder game design, the Board class has a private constructor and a static synchronized getInstance() method. Which design pattern is applied here and why is it the correct choice?
easy
A. Singleton pattern, to ensure only one board instance exists during the game.
B. Factory pattern, because it controls object creation centrally.
C. Builder pattern, to incrementally construct the board with snakes and ladders.
D. Prototype pattern, to clone the board for multiple game sessions.

Solution

  1. Step 1: Identify the role of private constructor and static synchronized method

    The private constructor prevents external instantiation, and the synchronized getInstance() ensures thread-safe single instance creation.
  2. Step 2: Match to design pattern intent

    Singleton pattern ensures exactly one Board instance exists, which is critical to maintain consistent game state.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Singleton controls single instance creation with thread safety [check]
Hint: Private constructor + static getInstance() = Singleton pattern [check]
Common Mistakes:
3. In designing a Vehicle abstraction for a parking system, should Vehicle be an abstract class or an interface? Consider that vehicles have state like license plate and behavior like park().
easy
A. Abstract class, because it can hold shared state and provide default behavior implementations.
B. Interface, because state can be stored externally and behavior is all that matters.
C. Interface, because it allows multiple inheritance and defines behavior without state.
D. Abstract class, because it forces all subclasses to implement all methods explicitly.

Solution

  1. Step 1: Analyze state and behavior requirements

    Vehicles have shared state (e.g., license plate) and common behavior (e.g., park). Abstract classes can hold state and provide default method implementations.
  2. Step 2: Eliminate interface options

    Interfaces cannot hold state (prior to Java 8 default methods) and rely on external storage for state, which complicates design. Abstract class better encapsulates state and behavior.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Shared state + default behavior -> abstract class [check]
Hint: Stateful base class -> abstract class, not interface [check]
Common Mistakes:
4. You want to add a WeekendPermissionStrategy that changes file access permissions on weekends without modifying existing classes. Which SOLID principle guides the minimum change, and what is the correct approach?
medium
A. Single Responsibility Principle: modify the Directory class to handle weekend logic directly.
B. Liskov Substitution Principle: subclass File to override permission checks for weekends.
C. Open/Closed Principle: create a new WeekendPermissionStrategy implementing PermissionStrategy, inject it where needed.
D. Dependency Inversion Principle: invert dependencies by making Directory depend on concrete WeekendPermissionStrategy.

Solution

  1. Step 1: Identify the SOLID principle for extensibility without modification

    The Open/Closed Principle (OCP) states software entities should be open for extension but closed for modification.
  2. Step 2: Apply OCP by adding a new WeekendPermissionStrategy implementing existing PermissionStrategy interface

    This allows adding weekend-specific logic without changing existing Directory or File classes.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    New strategy class + interface -> OCP compliance [check]
Hint: Add new strategy class, don't modify existing code [check]
Common Mistakes:
5. To add support for ElectricCar needing ChargingSpot in the current parking lot design, what is the minimum change that respects extensibility and avoids modifying existing classes?
hard
A. Modify Vehicle base class to include charging logic and add ChargingSpot as a subclass of ParkingSpot.
B. Add charging logic inside ParkingLot class and create a new ChargingSpot type without changing enums.
C. Create a new ElectricVehicle interface and modify existing classes to implement it.
D. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility.COMPATIBILITY_MAP accordingly.

Solution

  1. Step 1: Identify extensibility without modifying existing classes

    Enums are extended with new constants; new subclass ElectricCar is created without changing existing classes.
  2. Step 2: Update compatibility map to include new vehicle and spot types

    SpotCompatibility.COMPATIBILITY_MAP is updated to reflect which spots fit ElectricCar, preserving OCP.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Extend enums + new subclass + update compatibility map -> no existing class modified [check]
Hint: Extend enums + new subclass + update map -> no existing class changed [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