Skip to content
LLD Learn/OOP Foundations & UML
Browsing as a guest. Sign in to save your progress and earn XP as you complete chapters.

The Four Pillars, Revisited for Interviews

7 min read

You'll learn to

  • -Explain encapsulation, abstraction, inheritance, and polymorphism with the nuance an interviewer expects, not just textbook definitions
  • -Spot when a candidate design leans on inheritance or getters/setters in a way that actually violates encapsulation

Every CS student can recite encapsulation, abstraction, inheritance, and polymorphism. What separates a strong LLD candidate is applying them with judgment instead of reciting them as trivia - because it is entirely possible to write code that technically has all four pillars and is still a bad design.

Encapsulation Is About Invariants, Not Just Private Fields

Slapping "private" on every field and generating a getter and setter for each one is not encapsulation - it is just a longer way to expose mutable state. Real encapsulation means a class protects its own invariants: an Account class should not let its balance go negative just because it exposed a setBalance() method. If every field has a public setter, external code can put the object into an invalid state, and the class has encapsulated nothing.

Encapsulation that actually protects an invariant
class Account:
    def __init__(self, balance: float):
        self._balance = balance

    def withdraw(self, amount: float) -> None:
        if amount > self._balance:
            raise ValueError("Insufficient funds")
        self._balance -= amount

    def balance(self) -> float:
        return self._balance
    # No set_balance() - the only way to change balance is through
    # a method that enforces the "never negative" invariant.

Abstraction: Hiding Complexity Behind the Right Contract

Abstraction means callers depend on what a class does, not how it does it. A PaymentProcessor.charge(amount) method is an abstraction over card networks, retries, and currency conversion - the caller never needs to know any of that. The interview-relevant nuance: a good abstraction is defined by what the caller actually needs, not by anticipating every possible future need. Over-abstracting (adding parameters and hooks nobody asked for) is its own design smell.

Inheritance and Polymorphism: Substitutability Is the Point

Inheritance is not primarily a code-reuse tool - that is a side effect. Its actual purpose is enabling polymorphism: code written against a base type should work correctly with any subtype, without knowing which one it got. When an interviewer asks you to design a payment system with CreditCard, DebitCard, and Wallet, the win is not that the three classes share code - it is that the checkout flow can call process(payment) once and work for all three, with no type-checking branch anywhere.

A quick sanity check for any inheritance relationship: can you truthfully say "a [Subclass] is a [Superclass]"? "A DebitCard is a Payment" holds up. "A Square is a Rectangle" does not, mathematically, hold up the way most people assume - more on that in the Liskov Substitution chapter.

Interview Signal

Why does a class with a public getter and setter for every private field not count as good encapsulation?

Weak Answer

"It does count - all the fields are private, so the data is protected."

Strong Answer

"Making fields private only to expose an unrestricted setter for each one doesn't protect anything - external code can still put the object into any state, including invalid ones. Real encapsulation means the class's methods enforce its invariants, so it's impossible to construct an invalid instance through the public interface."

Check Yourself1 / 3

What makes encapsulation more than just "making fields private"?

ScaleDojo Logo
Initializing ScaleDojo