Bird
Raised Fist0
Interview Prepoop-design-patternsmediumAmazonGoogleMicrosoftFlipkartRazorpaySwiggy

Abstraction - Abstract Class vs Interface - When to Use Which

Choose your preparation mode3 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
🎯
Abstraction - Abstract Class vs Interface - When to Use Which
mediumOOPAmazonGoogleMicrosoft

Imagine designing a vehicle system where you want to enforce certain behaviors but also allow flexibility in implementation. Choosing between abstract classes and interfaces can make or break your design.

💡 Beginners often confuse abstract classes and interfaces as interchangeable or think interfaces can contain implementation like classes, missing the subtle design intent behind each.
📋
Interview Question

Explain the difference between an abstract class and an interface in object-oriented programming. When should you use an abstract class versus an interface?

Abstraction as hiding implementation detailsContract definition via interfacesPartial implementation via abstract classes
💡
Scenario & Trace
ScenarioDesigning a payment processing system supporting multiple payment methods
Define an interface 'PaymentMethod' with methods like 'authorize' and 'capture' to enforce a contract. Use an abstract class 'BasePayment' to provide common code like logging or validation that all payment methods share. Concrete classes like 'CreditCardPayment' and 'UPIPayment' implement the interface and extend the abstract class to reuse code and fulfill the contract.
ScenarioBuilding a GUI framework with various UI components
Create an abstract class 'UIComponent' that provides default implementations for rendering and event handling. Define an interface 'Clickable' to specify the contract for click behavior. Components like 'Button' extend 'UIComponent' and implement 'Clickable' to combine shared behavior and specific contracts.
  • When a class needs to inherit behavior from multiple sources but the language restricts multiple inheritance of classes
  • When default method implementations are added to interfaces (e.g., Java 8+), blurring lines between abstract classes and interfaces
  • When performance or memory constraints favor one abstraction over the other due to language-specific implementation details
⚠️
Common Mistakes
Thinking interfaces can contain full method implementations like classes

Interviewer doubts your understanding of interface purpose and language features

Clarify that traditionally interfaces only declare methods, but some languages allow default methods with limited implementation

Believing a class can inherit multiple abstract classes

Interviewer suspects you don’t understand inheritance limitations and design constraints

Explain that most languages allow single inheritance of classes but multiple interface implementations

Using abstract classes when only a contract is needed, leading to rigid designs

Interviewer sees poor design choices and lack of flexibility

Use interfaces to define contracts when no shared code is needed, enabling flexible and decoupled designs

Ignoring language-specific features like default methods or sealed interfaces

Interviewer thinks you lack up-to-date knowledge and practical experience

Mention modern language features and how they affect design decisions

🧠
Basic Definition - What It Is
💡 This level covers the fundamental difference and purpose of abstract classes and interfaces, enough to answer basic interview questions.

Intuition

Abstract classes provide partial implementation; interfaces define a contract without implementation.

Explanation

An abstract class is a class that cannot be instantiated on its own and may contain both abstract methods (without implementation) and concrete methods (with implementation). It allows sharing common code among related classes. An interface is a pure contract that specifies methods a class must implement but does not provide any implementation itself (except in some modern languages with default methods). Interfaces enable multiple inheritance of type and define capabilities that unrelated classes can share.

Memory Hook

💡 Think of an abstract class as a partially built house you can’t live in yet, and an interface as a blueprint that anyone can follow to build their own house.

Interview Questions

What is the main difference between an abstract class and an interface?
  • Abstract class can have implemented methods; interface usually cannot
  • A class can inherit only one abstract class but multiple interfaces
Depth Level
Interview Time30 seconds
Depthbasic

Covers fundamental definitions and differences; sufficient for screening rounds.

Interview Target: Minimum floor - never go below this

Knowing only this will help you pass initial screening but not detailed technical rounds.

🧠
Mechanism Depth - How It Works
💡 This level explains internal workings, language-specific nuances, and design trade-offs expected in product company interviews.

Intuition

Abstract classes enable code reuse and partial abstraction; interfaces define strict contracts enabling multiple inheritance of type and flexible design.

Explanation

Abstract classes allow you to define some methods with implementation and some without, enabling subclasses to inherit common behavior and override or implement abstract methods. They are useful when classes share a common ancestor and behavior. Interfaces define a set of methods that implementing classes must provide, enforcing a contract without dictating how it is done. Modern languages like Java 8+ allow default methods in interfaces, providing limited implementation and blurring traditional distinctions. Interfaces support multiple inheritance of type, allowing a class to implement multiple interfaces, which is not possible with classes in many languages. Choosing between them depends on whether you need to share code (abstract class) or just enforce a contract (interface), and on language constraints like single inheritance.

Memory Hook

💡 Abstract class is a half-finished machine you can customize; interface is a checklist you must complete regardless of your machine’s design.

Interview Questions

When would you prefer an abstract class over an interface?
  • When you want to share common code among related classes
  • When you want to provide default behavior that subclasses can override
  • When you want to control the inheritance hierarchy
How do interfaces support multiple inheritance?
  • A class can implement multiple interfaces, inheriting multiple contracts
  • This avoids diamond problem since interfaces usually don’t have state
  • Abstract classes do not support multiple inheritance in many languages
Depth Level
Interview Time2-3 minutes
Depthintermediate

Demonstrates understanding of design trade-offs, language features, and practical usage.

Interview Target: Target level for FAANG on-sites

Mastering this level distinguishes you from most candidates and prepares you for system design discussions.

📊
Explanation Depth Levels
💡 Choose your explanation depth based on interview stage and company expectations.
LevelInterview TimeSuitable ForRisk
Basic Definition30sScreening call or initial HR roundToo shallow for technical on-site interviews
Mechanism Depth2-3 minutesTechnical phone screens and on-site interviews at product companiesNone if well-prepared; demonstrates strong conceptual understanding
💼
Interview Strategy
💡 Use this guide to structure your explanation clearly and confidently before every interview.

How to Present

Start with a clear definition of abstract classes and interfacesGive a real-world analogy or example to illustrate the differenceExplain the internal mechanism and language-specific nuancesDiscuss edge cases and when to choose one over the other

Time Allocation

Definition: 30s → Example: 1min → Mechanism: 2min → Edge cases: 30s. Total ~4min

What the Interviewer Tests

Interviewer tests your understanding of abstraction, design trade-offs, and ability to apply concepts in real scenarios.

Common Follow-ups

  • Can interfaces have method implementations? Explain with examples.
  • What happens if a class implements two interfaces with conflicting default methods?
💡 These follow-ups check your knowledge of modern language features and conflict resolution.
🔍
Pattern Recognition

When to Use

Asked when discussing OOP fundamentals, design principles, or when designing class hierarchies and APIs.

Signature Phrases

'Explain the difference between abstract class and interface''Compare abstract class vs interface''When would you use an interface instead of an abstract class?'

NOT This Pattern When

Similar Problems

Practice

(1/5)
1. When a class inherits from multiple classes that have a method with the same name, describe the step-by-step process the Method Resolution Order (MRO) uses to determine which method is called.
easy
A. MRO uses a linearization algorithm that merges the order of parents and their ancestors to find the method.
B. MRO searches the first parent class fully before moving to the next parent class.
C. MRO always calls the method from the last parent class listed in the inheritance.
D. MRO randomly picks the method from any parent class that defines it.

Solution

  1. Step 1: Understand naive search

    MRO does not simply search the first parent class fully before moving to the next; it uses a more sophisticated approach.
  2. Step 2: Recognize MRO linearization

    MRO uses a specific linearization (like C3 linearization) that merges parent classes and their ancestors in a consistent order.
  3. Step 3: Eliminate incorrect options

    MRO always calls the method from the last parent class listed in the inheritance is incorrect because the last parent is not always chosen; order and ancestors matter. MRO randomly picks the method from any parent class that defines it is incorrect because MRO is deterministic, not random.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    MRO merges inheritance hierarchies to find the correct method in a predictable order.
Hint: MRO = deterministic linearization of inheritance graph
Common Mistakes:
  • Assuming simple left-to-right search suffices
  • Believing last parent always overrides
  • Thinking method choice is random
2. What is a key trade-off or limitation when using multiple inheritance to solve the Diamond Problem in object-oriented design?
medium
A. Multiple inheritance always leads to ambiguous method calls that cannot be resolved.
B. Multiple inheritance eliminates the need for Method Resolution Order (MRO).
C. Multiple inheritance reduces code reuse compared to single inheritance.
D. Using multiple inheritance can increase complexity and make the class hierarchy harder to understand and maintain.

Solution

  1. Step 1: Understand the Diamond Problem

    Diamond Problem arises when a class inherits from two classes that share a common ancestor, causing ambiguity.
  2. Step 2: Evaluate Multiple inheritance always leads to ambiguous method calls that cannot be resolved.

    Multiple inheritance can cause ambiguity, but languages use MRO to resolve it, so it is not always unresolved.
  3. Step 3: Evaluate Multiple inheritance eliminates the need for Method Resolution Order (MRO).

    MRO is essential in multiple inheritance to resolve method calls, so multiple inheritance does not eliminate MRO.
  4. Step 4: Evaluate Multiple inheritance reduces code reuse compared to single inheritance.

    Multiple inheritance generally increases code reuse by combining features from multiple classes.
  5. Step 5: Correct trade-off

    Using multiple inheritance can increase complexity and make the class hierarchy harder to understand and maintain. correctly identifies that multiple inheritance increases complexity and can make hierarchies harder to maintain.
  6. Final Answer:

    Option D -> Option D
  7. Quick Check:

    Complexity and maintainability are key trade-offs in multiple inheritance.
Hint: Multiple inheritance = power with complexity cost
Common Mistakes:
  • Believing multiple inheritance always causes irresolvable ambiguity
  • Thinking MRO is unnecessary with multiple inheritance
  • Assuming multiple inheritance reduces code reuse
3. Identify the bug in the following singleton implementation that aims to use lazy initialization with double-checked locking in Java-like pseudocode:
class Singleton {
    private static Singleton instance;

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized(Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
What is the subtle bug that can cause thread-safety issues?
medium
A. The synchronized block is too large, causing unnecessary locking overhead.
B. The instance variable is not declared volatile, risking instruction reordering.
C. The first null check outside synchronized block is redundant and should be removed.
D. The constructor is not private, allowing multiple instances externally.

Solution

  1. Step 1: Analyze double-checked locking correctness

    Without volatile, the instance reference may be visible before full construction due to instruction reordering.
  2. Step 2: Check other options

    Synchronized block size is minimal and correct; first null check is necessary for performance; constructor privacy is unrelated to this snippet.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Missing volatile causes subtle thread-safety bugs [OK]
Hint: Volatile prevents instruction reordering in double-checked locking [OK]
Common Mistakes:
  • Ignoring volatile keyword necessity
  • Thinking synchronized block size is the bug
  • Assuming constructor privacy is the main issue here
4. Suppose you want to extend the Command Pattern to support commands that can be executed multiple times (reused) and also support undo/redo correctly. Which modification to the invoker's undo/redo management is necessary to handle this scenario without corrupting state?
hard
A. Store only one instance of each command and reuse it for all executions, pushing it multiple times onto undo stack.
B. Clear both undo and redo stacks after every command execution to avoid reuse issues.
C. Create a new command instance for each execution and push that instance onto the undo stack, ensuring undo/redo operate on the correct state snapshot.
D. Avoid using undo/redo stacks and instead recompute state from scratch on each undo or redo.

Solution

  1. Step 1: Understand reuse implications

    Reusing the same command instance for multiple executions causes undo/redo to affect the wrong state because the command's internal state may change.
  2. Step 2: Identify correct approach

    Creating a new command instance per execution ensures each undo/redo corresponds to the exact executed command instance and its parameters.
  3. Step 3: Confirm undo/redo stack integrity

    This approach preserves correct ordering and state consistency during undo/redo operations.
  4. Final Answer:

    Option C -> Option C
  5. Quick Check:

    New instances per execution prevent state corruption on undo/redo [OK]
Hint: Each execution needs a fresh command instance for correct undo/redo [OK]
Common Mistakes:
  • Reusing command instances causing incorrect undos
  • Clearing stacks unnecessarily losing history
5. If the Snake and Ladder game is extended to support multiple concurrent games running in parallel, which design consideration is most critical to avoid shared state bugs?
hard
A. Ensuring each game instance has its own independent GameController and Player objects
B. Centralizing player positions in a global data structure accessible by all games
C. Sharing the Dice instance across games to reduce resource usage
D. Using a singleton pattern for the Board class to ensure consistency across games

Solution

  1. Step 1: Singleton Board pattern

    Incorrect: Singleton would cause shared state across games, leading to conflicts.
  2. Step 2: Independent GameController and Player per game

    Correct: Isolates state per game, preventing interference.
  3. Step 3: Sharing Dice instance

    Incorrect: Shared Dice can cause race conditions or inconsistent rolls.
  4. Step 4: Global player positions

    Incorrect: Global state breaks isolation and causes bugs.
  5. Final Answer:

    Option A -> Option A
  6. Quick Check:

    Isolating state per game instance is key for concurrency safety.
Hint: Isolate state per game instance to avoid concurrency bugs [OK]
Common Mistakes:
  • Using singleton for shared components without considering concurrency
  • Sharing mutable objects like Dice across threads
  • Centralizing state globally ignoring isolation