Bird
Raised Fist0
Interview Prepoop-design-patternseasyAmazonGoogleMicrosoftTCSInfosysWiproFlipkart

Encapsulation - Data Hiding, Getters/Setters & Access Modifiers

Choose your preparation mode3 modes available
▶
Steps
setup

Define Class Person with Private Fields

The class 'Person' is defined with two private fields: '_name' of type String and '_age' of type int. These fields are not accessible outside the class directly.

💡 Private fields prevent external code from directly accessing or modifying sensitive data, enforcing encapsulation.
Line:class Person: def __init__(self): self._name = None self._age = None
💡 Data hiding is implemented by marking fields as private (underscore prefix in Python).
📊
Encapsulation - Data Hiding, Getters/Setters & Access Modifiers - Watch the Algorithm Execute, Step by Step
Watching this step-by-step helps you understand how encapsulation protects data and how getters/setters provide controlled access, which is hard to grasp by just reading code.
Step 1/11
·Active fill★Answer cell
Private fields enforce data hiding.
Person
−_name: String
−_age: int
Getter method added for controlled access.
Person
−_name: String
−_age: int
+getName()
Setter method added for controlled modification.
Person
−_name: String
−_age: int
+getName()
+setName()
Getter method added for '_age'.
Person
−_name: String
−_age: int
+getName()
+setName()
+getAge()
Setter method added for '_age'.
Person
−_name: String
−_age: int
+getName()
+setName()
+getAge()
+1 more
Instance created to demonstrate encapsulation in action.
Person
−_name: String
−_age: int
+getName()
+setName()
+getAge()
+1 more
Setter method used to update private field.
Person
−_name: String
−_age: int
+getName()
+setName()
+getAge()
+1 more
Setter method used to update private field.
Person
−_name: String
−_age: int
+getName()
+setName()
+getAge()
+1 more
Getter method used to access private field.
Person
−_name: String
−_age: int
+getName()
+setName()
+getAge()
+1 more
Getter method used to access private field.
Person
−_name: String
−_age: int
+getName()
+setName()
+getAge()
+1 more
Encapsulation pattern demonstrated fully.
Person
−_name: String
−_age: int
+getName()
+setName()
+getAge()
+1 more

Key Takeaways

✓ Encapsulation hides internal data by making fields private and exposes controlled access via public getters and setters.

Reading code alone may not reveal how data hiding protects integrity; watching the step-by-step shows how access is controlled.

✓ Getters and setters provide a safe interface to read and modify private data, allowing validation or logic to be added if needed.

Seeing the methods added and used clarifies their role beyond just simple data access.

✓ Creating an instance and using getters/setters demonstrates encapsulation in action, showing how objects protect their own state.

Understanding encapsulation requires seeing both the class design and how instances interact with it.

Practice

(1/5)
1. Imagine a class responsible for both data persistence and data validation. When a change in validation rules occurs, trace the impact on the class and explain what happens step-by-step.
easy
A. Only the validation methods need modification; persistence remains unaffected, so SRP is maintained.
B. Changing validation rules forces modifying the entire class, risking unintended side effects on persistence logic.
C. Validation changes automatically propagate to persistence without code changes due to tight coupling.
D. Persistence logic will break because validation and persistence are tightly integrated and inseparable.

Solution

  1. Step 1: Identify responsibilities

    The class handles both validation and persistence, two distinct reasons to change.
  2. Step 2: Trace change impact

    Changing validation rules requires modifying validation code inside the class.
  3. Step 3: Side effects

    Because persistence logic shares the class, changes risk affecting persistence unintentionally, increasing maintenance risk.
  4. Step 4: SRP violation

    This coupling violates SRP, as one reason to change (validation) affects unrelated functionality (persistence).
  5. Final Answer:

    Option B -> Option B
  6. Quick Check:

    One reason to change should not force changes in unrelated code -> SRP violation.
Hint: One reason to change means one place to modify.
Common Mistakes:
  • Assuming changes affect only related methods without side effects.
  • Believing tight coupling is harmless if code is in one class.
  • Thinking validation and persistence are always linked.
2. You have a payment processing system that currently uses multiple if-else statements to handle different payment methods like credit card, UPI, and net banking. The system needs to be extended frequently with new payment methods without modifying existing code. Which design approach best addresses this requirement?
easy
A. Use a brute force approach with nested if-else statements for each payment method.
B. Implement a strategy pattern where each payment method is encapsulated in its own class implementing a common interface.
C. Use a recursive function that selects payment methods based on input parameters.
D. Apply a greedy algorithm to select the payment method with the lowest processing fee.

Solution

  1. Step 1: Understand the problem of frequent extension

    The system requires adding new payment methods without modifying existing code, which violates the open-closed principle if using if-else chains.
  2. Step 2: Identify the design pattern that encapsulates behaviors

    The strategy pattern encapsulates each payment method in its own class implementing a common interface, allowing easy extension by adding new classes without changing existing code.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Strategy pattern replaces conditionals with polymorphism [OK]
Hint: Replacing conditionals with polymorphism enables easy extension [OK]
Common Mistakes:
  • Thinking recursion or greedy algorithms solve extensibility here
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. If the parking lot system needs to support dynamic pricing based on spot location, time, and vehicle type, which design approach best supports this extensibility without modifying existing classes?
hard
A. Use the Strategy pattern to encapsulate different pricing algorithms and assign them dynamically
B. Add pricing logic directly inside the ParkingSpot class with multiple if-else conditions
C. Hardcode pricing rules in the ParkingLot class for all spot and vehicle combinations
D. Create separate subclasses of ParkingSpot for each pricing rule variant

Solution

  1. Step 1: Identify extensibility needs

    Pricing rules vary by multiple factors and may change frequently.
  2. Step 2: Evaluate design options

    Embedding logic in ParkingSpot or ParkingLot leads to rigid, hard-to-maintain code. Subclass explosion is unmanageable.
  3. Step 3: Recognize Strategy pattern benefits

    Strategy encapsulates pricing algorithms, allowing dynamic assignment and easy extension without modifying existing classes.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    Strategy pattern supports flexible, maintainable pricing logic [OK]
Hint: Use Strategy pattern to keep pricing logic flexible and decoupled [OK]
Common Mistakes:
  • Embedding complex logic inside core classes
  • Using inheritance for every pricing variant
5. Suppose you want to extend the observer pattern to allow observers to receive multiple notifications for the same event type without unsubscribing (i.e., observers can be registered multiple times for the same event). Which modification to the thread-safe observer pattern implementation below correctly supports this requirement without breaking thread safety or notification correctness? Options: A) Change the observers data structure from a set to a list per event type and allow duplicates. B) Keep using a set but add a counter for each observer to track multiple subscriptions. C) Use a dictionary mapping observers to their subscription counts per event type. D) Use a queue per event type to enqueue notifications and process them asynchronously.
hard
A. Keep using a set but add a counter for each observer to track multiple subscriptions.
B. Change the observers data structure from a set to a list per event type and allow duplicates.
C. Use a dictionary mapping observers to their subscription counts per event type.
D. Use a queue per event type to enqueue notifications and process them asynchronously.

Solution

  1. Step 1: Understand the requirement

    Observers can subscribe multiple times to the same event type and should receive multiple notifications accordingly.
  2. Step 2: Evaluate data structure changes

    Using a set alone disallows duplicates. A list allows duplicates but is not thread-safe and inefficient for removals. A dictionary mapping observers to counts tracks multiple subscriptions safely.
  3. Step 3: Choose the best approach

    Adding a counter per observer in the set (Keep using a set but add a counter for each observer to track multiple subscriptions.) or using a dictionary (Use a dictionary mapping observers to their subscription counts per event type.) can work, but adding a counter per observer in the set is simpler and keeps thread safety with minimal changes.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    Counting subscriptions per observer preserves multiple notifications safely [OK]
Hint: Track subscription counts to allow multiple notifications [OK]
Common Mistakes:
  • Using list causes concurrency issues and inefficient removals
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