Bird
Raised Fist0
Interview Prepoop-design-patternsmediumAmazonGoogleMicrosoftFlipkartSwiggyRazorpayCRED

Composition vs Inheritance - Favour Composition, Why & When

Choose your preparation mode3 modes available
🎯
Composition vs Inheritance - Favour Composition, Why & When
mediumOOPAmazonGoogleMicrosoft

Imagine building a car software system where you want to add new features without breaking existing ones. Should you inherit from a base car class or compose smaller feature modules? This dilemma highlights the importance of choosing between inheritance and composition.

💡 Beginners often confuse inheritance as the default way to reuse code and model relationships, overlooking how it can tightly couple classes and reduce flexibility.
📋
Interview Question

Explain the difference between composition and inheritance in object-oriented design. Why is composition often preferred over inheritance? When should you favour one over the other?

is-a vs has-a relationshipscoupling and flexibility in designcode reuse and maintainability
💡
Scenario & Trace
ScenarioDesigning a game character system where characters can have different abilities like flying, swimming, or shooting.
Using inheritance, you might create subclasses like FlyingCharacter, SwimmingCharacter, etc., leading to a complex hierarchy. Using composition, you create a Character class that contains Ability objects (FlyAbility, SwimAbility), allowing dynamic addition/removal of abilities without changing the class hierarchy.
ScenarioBuilding a UI framework where buttons and text fields share common behaviors but also have unique features.
Inheritance might force all UI elements into a rigid hierarchy, making it hard to add new behaviors. Composition allows UI elements to include behavior components (e.g., Clickable, Draggable), promoting reuse and flexibility.
  • When a subclass needs to override multiple behaviors from the parent class → inheritance can cause fragile base class problems
  • When runtime behavior needs to change dynamically → composition supports this better than static inheritance
  • When the domain naturally fits an 'is-a' relationship with stable hierarchy → inheritance might be simpler and more intuitive
⚠️
Common Mistakes
Thinking inheritance is always better for code reuse

Interviewer suspects lack of understanding of coupling and flexibility issues

✅ Explain that inheritance can cause tight coupling and fragile designs; composition offers more flexible reuse

Confusing 'is-a' and 'has-a' relationships

Interviewer doubts your grasp of fundamental OOP relationships

✅ Clarify that inheritance models 'is-a' and composition models 'has-a' relationships

Ignoring runtime flexibility benefits of composition

Interviewer thinks you lack practical design experience

✅ Highlight how composition allows changing behavior dynamically by swapping components

Assuming inheritance is always simpler

Interviewer questions your understanding of maintenance and scalability

✅ Discuss how inheritance hierarchies can become complex and brittle, making maintenance harder

🧠
Basic Definition - What It Is
💡 This level covers the fundamental difference and basic intuition behind the two concepts.

Intuition

Inheritance models an 'is-a' relationship by extending a class, while composition models a 'has-a' relationship by including objects.

Explanation

Inheritance allows a class to inherit properties and behaviors from a parent class, establishing a tight relationship and enabling code reuse. Composition involves building classes by combining objects of other classes, promoting flexibility by delegating responsibilities. Favoring composition helps avoid deep inheritance hierarchies and reduces coupling, making systems easier to maintain and extend.

Memory Hook

💡 Think of inheritance as a family tree (child is a type of parent), and composition as assembling a toolkit (an object has tools it uses).

Interview Questions

❓ What is the main difference between inheritance and composition?
  • Inheritance is an 'is-a' relationship
  • Composition is a 'has-a' relationship
  • Composition promotes looser coupling
⏱
Depth Level
Interview Time30 seconds
Depthbasic

Covers fundamental definitions and intuition; sufficient for quick screening questions.

Interview Target: Minimum floor - never go below this

Knowing only this will help you pass initial screening but not detailed design discussions.

🧠
Mechanism Depth - How It Works
💡 This level explains internal design trade-offs and practical implications expected in product company interviews.

Intuition

Composition enables flexible behavior by delegating responsibilities to contained objects, while inheritance creates a fixed class hierarchy that can be fragile and tightly coupled.

Explanation

Inheritance tightly couples child classes to parent implementations, making changes in the parent ripple through subclasses, which can cause fragility and limit reuse. Composition, by contrast, uses object references to delegate tasks, allowing behaviors to be changed at runtime or replaced without affecting the containing class. This reduces coupling and increases modularity. Favoring composition aligns with design principles like SOLID, especially the Open/Closed Principle and Dependency Inversion Principle. However, inheritance is still useful when there is a clear, stable 'is-a' relationship and shared behavior that should be enforced.

Memory Hook

💡 Composition is like building with LEGO blocks you can rearrange anytime; inheritance is like carving a sculpture from a single block.

Interview Questions

❓ Why is composition considered more flexible than inheritance?
  • Composition allows changing behavior at runtime
  • Inheritance creates tight coupling and fragile hierarchies
  • Composition supports better code reuse through delegation
❓ When would you still use inheritance over composition?
  • When there is a clear 'is-a' relationship
  • When behavior is stable and unlikely to change
  • When you want to enforce a common interface or contract
⏱
Depth Level
Interview Time2-3 minutes
Depthintermediate

Demonstrates understanding of design trade-offs, coupling, and maintainability; suitable for FAANG on-sites.

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 quick conceptual questionsToo shallow for detailed design or system architecture interviews
Mechanism Depth2-3 minutesOn-site interviews at FAANG and top product companiesRequires good understanding of design principles and trade-offs
💼
Interview Strategy
💡 Use this guide to structure your explanation clearly and confidently before every mock or real interview.

How to Present

Start with a clear definition of inheritance and compositionGive a real-world analogy or example to illustrate the differenceExplain the internal mechanism and trade-offs between the twoDiscuss edge cases and when to prefer one over the other

Time Allocation

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

What the Interviewer Tests

Interviewer checks your understanding of object relationships, design flexibility, coupling, and practical application in design problems.

Common Follow-ups

  • What problems can deep inheritance hierarchies cause? → Fragility, tight coupling, difficulty in maintenance
  • How does composition support runtime behavior changes? → By delegating to contained objects that can be swapped or modified
💡 These follow-ups test your depth and ability to reason about design trade-offs.
🔍
Pattern Recognition

When to Use

Asked during OOP design, system design, or low-level design interviews when discussing class relationships and design flexibility.

Signature Phrases

Explain composition vs inheritanceCompare is-a and has-a relationshipsWhy favour composition over inheritance?

NOT This Pattern When

Similar Problems

Practice

(1/5)
1. You need to add multiple optional features to a core object dynamically at runtime without creating a subclass for every possible combination. Which design approach best supports this requirement?
easy
A. Apply memoization to cache feature combinations for reuse
B. Create a large inheritance hierarchy with subclasses for each feature combination
C. Use a greedy algorithm to select features based on priority
D. Use composition to wrap the core object with feature objects that add behavior dynamically

Solution

  1. Step 1: Understand the problem constraints

    The problem requires adding features dynamically without subclass explosion.
  2. Step 2: Identify the design pattern that supports dynamic behavior wrapping

    The Decorator Pattern uses composition to wrap objects and add behavior at runtime, avoiding subclassing for every combination.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Dynamic wrapping via composition avoids subclass explosion [OK]
Hint: Dynamic wrapping avoids subclass explosion [OK]
Common Mistakes:
  • Thinking subclassing is the only way to add features
  • Confusing greedy algorithms with design patterns
2. Given the following Python code using the Builder pattern, what is the output of print(house) after constructing a basic house with the Director?
easy
A. House parts: Walls, Roof
B. House parts: Walls, Roof, Pool
C. House parts: Roof, Walls
D. House parts: Pool

Solution

  1. Step 1: Trace Director.construct_basic_house()

    The Director calls build_walls() and build_roof() on the builder, adding "Walls" and "Roof" to the house parts.
  2. Step 2: Check the final house parts list

    The house parts list contains ["Walls", "Roof"]. The pool is not added in this method.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Only walls and roof are added in basic house construction [OK]
Hint: Basic house adds walls and roof only [OK]
Common Mistakes:
  • Assuming pool is added by default
  • Mixing order of parts
3. You are designing a payment processing system that must support new payment methods without changing existing code. Which design approach best aligns with the Open/Closed Principle?
easy
A. Creating a new subclass for each payment method that implements a common payment interface
B. Modifying the existing payment processor class to handle new payment methods directly
C. Adding new conditional branches inside the existing payment processor class for each new payment method
D. Using global variables to switch between payment methods at runtime

Solution

  1. Step 1: Identify extension vs modification

    Adding new payment methods should extend behavior without modifying existing classes.
  2. Step 2: Evaluate subclassing with common interface

    Creating subclasses for each payment method allows extension by adding new classes, adhering to OCP.
  3. Step 3: Why other options fail

    Adding new conditional branches inside the existing payment processor class for each new payment method and modifying existing code violate the 'closed for modification' part. Using global variables to switch between payment methods at runtime uses global state, which is unrelated and error-prone.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    Extension via polymorphism, no modification of existing code.
Hint: Extend with new classes, don't modify existing ones [OK]
Common Mistakes:
  • Thinking adding conditionals is extension
  • Believing modifying existing code is acceptable if tested
  • Confusing global state management with OCP
4. If a new requirement arises where an interface needs to add a method without breaking existing implementations, what is the best approach to handle this in a language that originally did not support default methods in interfaces?
hard
A. Add the method to the interface and require all implementers to update their code immediately.
B. Create a new interface that extends the original and adds the new method, then update clients to use the new interface.
C. Add the method as a static method in the interface.
D. Convert the interface into an abstract class and provide a default implementation for the new method.

Solution

  1. Step 1: Understand backward compatibility

    Adding a method directly to an interface breaks existing implementers if no default implementation exists.
  2. Step 2: Why converting to abstract class is problematic

    Changing interface to abstract class breaks existing multiple inheritance and design contracts.
  3. Step 3: Using interface extension

    Creating a new interface that extends the original preserves backward compatibility and allows gradual adoption.
  4. Step 4: Static methods in interfaces

    Static methods do not affect instance method contracts and cannot replace instance methods.
  5. Final Answer:

    Option B -> Option B
  6. Quick Check:

    Extending interfaces is the safe way to evolve contracts without breaking clients.
Hint: Extend interfaces to add methods without breaking existing code.
Common Mistakes:
  • Assuming all implementers can update immediately.
  • Thinking abstract classes can replace interfaces without impact.
  • Confusing static methods with instance methods in interfaces.
5. Suppose you want to add logging and caching to a remote service without modifying its code. You also want to control access based on user roles. Which combination of structural patterns would best address these requirements?
hard
A. Use a Facade to control access and an Adapter to add logging and caching
B. Use an Adapter to convert the service interface and a Facade to simplify access
C. Use a Proxy to control access and a Decorator to add logging and caching
D. Use a Proxy to add logging and caching and an Adapter to control access

Solution

  1. Step 1: Analyze requirements

    Control access by user roles -> Proxy fits. Add logging and caching without modifying code -> Decorator fits.
  2. Step 2: Evaluate options

    A incorrectly assigns Facade for access control and Adapter for logging/caching. B misuses Adapter and Facade roles. C correctly assigns Proxy for access control and Decorator for adding behavior. D incorrectly uses Adapter for access control and Proxy for logging/caching.
  3. Final Answer:

    Option C -> Option C
Hint: Proxy = access control; Decorator = add behavior; Adapter = interface conversion; Facade = simplify interface
Common Mistakes:
  • Confusing Proxy and Decorator responsibilities
  • Using Adapter or Facade for access control
  • Assuming Proxy can add behavior like logging and caching
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