Bird
Raised Fist0
Interview Prepoop-design-patternsmediumAmazonGoogleMicrosoftFlipkartRazorpaySwiggy

Abstraction - Abstract Class vs Interface - When to Use Which

Choose your preparation mode3 modes available
▶
Steps
setup

Define Abstract Class Shape

We start by defining an abstract class named 'Vehicle' with protected fields and an abstract method 'move'. This sets the base for shared behavior.

💡 Defining an abstract class establishes a common template with some implemented details and some abstract methods to be implemented by subclasses.
Line:abstract class Vehicle { protected int speed; public abstract void move(); }
💡 Abstract classes can have fields and abstract methods, allowing partial implementation.
📊
Abstraction - Abstract Class vs Interface - When to Use Which - Watch the Algorithm Execute, Step by Step
Watching this visualization helps you grasp the conceptual differences and usage scenarios of abstract classes and interfaces by seeing their structure and relationships evolve incrementally.
Step 1/11
·Active fill★Answer cell
Demonstrates abstraction by defining an abstract class with fields and abstract methods.
«abstract»Vehicle
#speed: int
+move()
Defines an interface to specify behavior without implementation.
«abstract»Vehicle
#speed: int
+move()
«interface»Movable
+move()
Shows concrete class inheriting from abstract class and implementing abstract methods.
«abstract»Vehicle
#speed: int
+move()
«interface»Movable
+move()
Car
+move()
Car ▷ Vehicle (1:1)
Shows concrete class implementing an interface and fulfilling its contract.
«abstract»Vehicle
#speed: int
+move()
«interface»Movable
+move()
Car
+move()
Bike
+move()
Car ▷ Vehicle (1:1)Bike → Movable (1:1)
Emphasizes abstract class capabilities for code reuse and state.
«abstract»Vehicle
#speed: int
+move()
«interface»Movable
+move()
Car
+move()
Bike
+move()
Car ▷ Vehicle (1:1)Bike → Movable (1:1)
Emphasizes interface role in multiple inheritance and pure abstraction.
«abstract»Vehicle
#speed: int
+move()
«interface»Movable
+move()
Car
+move()
Bike
+move()
Car ▷ Vehicle (1:1)Bike → Movable (1:1)
Demonstrates inherited fields usage in concrete subclass.
«abstract»Vehicle
#speed: int
+move()
«interface»Movable
+move()
Car
#speed: int
+move()
Bike
+move()
Car ▷ Vehicle (1:1)Bike → Movable (1:1)
Shows interface implementation without inherited fields.
«abstract»Vehicle
#speed: int
+move()
«interface»Movable
+move()
Car
#speed: int
+move()
Bike
+move()
Car ▷ Vehicle (1:1)Bike → Movable (1:1)
Decision step emphasizing abstract class use for shared state.
«abstract»Vehicle
#speed: int
+move()
«interface»Movable
+move()
Car
#speed: int
+move()
Bike
+move()
Car ▷ Vehicle (1:1)Bike → Movable (1:1)
Decision step emphasizing interface use for multiple behavior contracts.
«abstract»Vehicle
#speed: int
+move()
«interface»Movable
+move()
Car
#speed: int
+move()
Bike
+move()
Car ▷ Vehicle (1:1)Bike → Movable (1:1)
Final summary of abstraction usage guidelines.
«abstract»Vehicle
#speed: int
+move()
«interface»Movable
+move()
Car
#speed: int
+move()
Bike
+move()
Car ▷ Vehicle (1:1)Bike → Movable (1:1)

Key Takeaways

✓ Abstract classes allow sharing code and state among related classes while enforcing some methods to be implemented.

This is hard to see from code alone because the combination of implemented and abstract members is subtle without visualization.

✓ Interfaces define pure behavior contracts without state, enabling multiple inheritance and flexible design.

Visualizing the lack of fields and the implementation relationship clarifies interface purpose better than reading code.

✓ Choosing between abstract class and interface depends on whether shared state or multiple behavior contracts are needed.

The decision steps explicitly show criteria that are often implicit or scattered in textual explanations.

Practice

(1/5)
1. Trace the sequence of events when a client tries to update a private field via a setter method in an encapsulated class.
easy
A. The client directly modifies the private field without any method call
B. The getter method is called first to check the current value before updating
C. The setter method validates the input, updates the private field, then returns control to the client
D. The private field is copied to a public variable which the client modifies

Solution

  1. Step 1: Identify encapsulation flow

    Private fields cannot be accessed directly; setters provide controlled access.
  2. Step 2: Follow setter method process

    Setter receives input, validates it, updates the private field, then returns control.
  3. Step 3: Analyze incorrect options

    The client directly modifies the private field without any method call violates data hiding. The getter method is called first to check the current value before updating misuses getter before setter. The private field is copied to a public variable which the client modifies breaks encapsulation by exposing private data.
  4. Final Answer:

    Option C -> Option C
  5. Quick Check:

    Setters control updates with validation, preserving encapsulation.
Hint: Setters validate and update private data, not direct access [OK]
Common Mistakes:
  • Assuming direct field access through setters
  • Confusing getter and setter roles
  • Thinking private data is copied out for modification
2. You need to traverse a tree-like structure where each node can be either a single element or a composite containing multiple child elements. The traversal should allow clients to iterate over all elements uniformly without exposing the internal structure. Which design approach best fits this requirement?
easy
A. Implement the Composite pattern combined with an Iterator interface to provide a unified traversal abstraction.
B. Use a recursive brute force traversal that manually visits each node and its children.
C. Apply a greedy algorithm that visits nodes based on a heuristic to minimize traversal time.
D. Use dynamic programming to store and reuse traversal results for overlapping subtrees.

Solution

  1. Step 1: Understand the problem structure

    The problem involves a tree with nodes that can be leaves or composites containing children, requiring uniform traversal.
  2. Step 2: Identify the suitable pattern

    The Composite pattern allows treating individual objects and compositions uniformly, and combining it with an Iterator abstracts traversal details.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Composite + Iterator provides uniform traversal abstraction [OK]
Hint: Composite + Iterator unifies traversal of tree structures [OK]
Common Mistakes:
  • Confusing traversal with greedy or DP approaches
  • Using manual recursion without abstraction
3. 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
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 Composite pattern iterator is extended to allow reusing leaf components multiple times during traversal (e.g., shared leaves), which modification is necessary to ensure correct iteration without infinite loops?
hard
A. No change needed; the existing iterator handles reuse naturally.
B. Modify the iterator to push children in original order instead of reversed order.
C. Add a visited set to track and skip already visited components during iteration.
D. Convert the iterator to a recursive traversal to handle reuse correctly.

Solution

  1. Step 1: Understand reuse implications

    Reusing leaves means the same component can appear multiple times, risking infinite loops.
  2. Step 2: Identify solution to prevent infinite loops

    Tracking visited components prevents revisiting the same node repeatedly during iteration.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Visited set avoids infinite loops with shared components [OK]
Hint: Track visited nodes to handle shared components safely [OK]
Common Mistakes:
  • Assuming no changes needed
  • Changing push order does not fix reuse loops
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