Interview Prep — OOP Track

OOP Interview Questions

15 OOP questions — the four pillars, SOLID principles, design patterns, and Python-specific OOP features. Tagged for FAANG and startups.

PillarsSOLIDPatternsPython OOP
15Total
4Pillars
5SOLID
3Patterns
3Python OOP
Progress saved locally. Check off questions — saves to your browser. No account needed.
0
/ 15 Done
01 What are the four pillars of OOP? OOP
  • Encapsulation: Bundling data and methods together; hiding internal state. Achieved via private/protected attributes in Python (_name, __name).
  • Abstraction: Exposing only essential features, hiding complexity. Abstract classes/interfaces define contracts.
  • Inheritance: A child class inherits attributes and methods from a parent class, enabling code reuse.
  • Polymorphism: Same interface, different behaviour. Method overriding (runtime) and method overloading (compile-time — not natively in Python).
02 What is polymorphism? Explain with a Python example. OOP
Polymorphism means "many forms" — objects of different classes can be treated through a common interface.
python
class Dog:
    def speak(self): return "Woof!"

class Cat:
    def speak(self): return "Meow!"

def make_sound(animal):
    print(animal.speak())

make_sound(Dog())  # Woof!
make_sound(Cat())  # Meow!
Types: Compile-time (overloading), Runtime (overriding), Duck typing.
03 What is encapsulation? How is it achieved in Python? OOP
Encapsulation bundles data and methods together while restricting direct access to internal state.

Python access conventions:
  • public — normal attribute (accessible everywhere)
  • _protected — convention, "please don't touch" (still accessible)
  • __private — name-mangled, harder to access (_ClassName__attr)
python
class BankAccount:
    def __init__(self):
        self.balance = 0       # public
        self._pin = "1234"     # protected
        self.__secret = "xyz"  # private

    def get_balance(self):
        return self.balance
04 What is abstraction? How is it different from encapsulation? OOP
Abstraction hides complex implementation details and shows only essential features.
Encapsulation hides internal state and requires interaction through methods.

Key difference: Abstraction = hiding complexity (design level). Encapsulation = hiding data (implementation level).
python
from abc import ABC, abstractmethod

class Payment(ABC):
    @abstractmethod
    def process_payment(self, amount):
        pass

class CreditCard(Payment):
    def process_payment(self, amount):
        print(f"Processing ${amount} via Credit Card")
05 Explain SOLID, one line each. OOP
Single responsibility: a class has one reason to change. Open/closed: open to extension, closed to modification. Liskov substitution: a subtype must work anywhere its base does. Interface segregation: many small interfaces beat one fat one. Dependency inversion: depend on abstractions, not concretions. They describe the same goal from five angles — change one part without breaking the others.
06 What is coupling and cohesion, and which way do you want each? OOP
Coupling is how much one module depends on another; cohesion is how related the things inside one module are. You want low coupling and high cohesion. A class that reaches into another's internals is tightly coupled, so a change there breaks it here. A class holding unrelated helpers has low cohesion, so every feature touches it and nothing has an obvious home.
07 What is the Law of Demeter, and what does breaking it look like? OOP
Talk only to your immediate collaborators. The tell is a chain: order.customer.address.city — that code now depends on three classes' internals, so a change to any of them breaks it. Ask the object for what you need (order.shipping_city()) rather than reaching through it.
08 Overloading vs overriding — and does Python have both? OOP
Overriding replaces an inherited method in a subclass; Python has it, resolved through the MRO at call time. Overloading means several methods with the same name and different signatures; Python does not have it — a later definition simply replaces the earlier one. The equivalents are default arguments, *args, or functools.singledispatch for genuine type-based dispatch.
09 What is an abstract class, and what happens if you instantiate one? OOP
A class that declares methods subclasses must implement and cannot itself be instantiated. In Python it comes from abc.ABC plus @abstractmethod; instantiating one raises TypeError listing the unimplemented methods. It exists to state a contract in code rather than a comment — the failure arrives at construction, not at the first call.
10 Explain inheritance types in Python with examples. OOP
  • Single: class B(A)
  • Multiple: class C(A, B) — Python uses MRO (Method Resolution Order) / C3 linearization
  • Multilevel: A → B → C (chain of inheritance)
  • Hierarchical: Multiple children from one parent
  • Hybrid: Combination of the above types
MRO: Use ClassName.__mro__ or help(ClassName) to inspect the resolution order in multiple inheritance.
11 What is the difference between @classmethod, @staticmethod, and instance method? OOP
python
class MyClass:
    count = 0

    def instance_method(self):   # access self & class
        return self

    @classmethod
    def class_method(cls):        # access class, not instance
        return cls.count

    @staticmethod
    def static_method(x):        # no self or cls
        return x * 2
Method typeFirst argUse case
Instance methodselfAccess/modify instance state
Class methodclsFactory methods, alternative constructors
Static methodUtility functions logically belonging to the class
12 What are dunder (magic) methods in Python? OOP
Dunder methods (double underscore) let you define how objects behave with built-in operators and functions.
  • __init__ — constructor
  • __str__, __repr__ — string representation
  • __len__len(obj)
  • __eq__, __lt__, __gt__ — comparison operators
  • __add__, __mul__ — arithmetic operators
  • __getitem__, __setitem__ — indexing obj[key]
  • __iter__, __next__ — make object iterable
  • __enter__, __exit__ — context manager protocol
python
class Vector:
    def __init__(self, x, y):
        self.x, self.y = x, y

    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)

    def __repr__(self):
        return f"Vector({self.x}, {self.y})"

v = Vector(1, 2) + Vector(3, 4)  # Vector(4, 6)
13 What is the difference between abstract class and interface in Python? OOP
AspectAbstract ClassInterface (Python pattern)
Concrete methodsAllowedNot allowed (all abstract)
StateCan have instance variablesTypically no state
Multiple inheritPossible but complexEncouraged
Python syntaxABC + mix of methodsABC with all @abstractmethod
Note: Python prefers "duck typing" over strict interfaces — "if it walks like a duck and quacks like a duck, it's a duck."
14 What are Python decorators in the context of classes? OOP
Common class decorators:
  • @property — getter method that looks like an attribute
  • @x.setter — setter with validation
  • @classmethod — receives class as first argument
  • @staticmethod — no self or cls
python
class Person:
    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        return self._name.title()

    @name.setter
    def name(self, value):
        if not value: raise ValueError("Name required")
        self._name = value

p = Person("alice")
print(p.name)   # Alice  (via @property getter)
p.name = "bob" # calls @name.setter
15 What is __slots__ and when should you use it? OOP
__slots__ restricts allowed attributes and saves memory by preventing automatic __dict__ creation per instance.
python
class Point:
    __slots__ = ['x', 'y']

    def __init__(self, x, y):
        self.x = x
        self.y = y

# p.z = 1  → AttributeError: 'Point' object has no attribute 'z'
Benefits:
  • 40–50% memory reduction when creating many instances
  • Faster attribute access
Drawback: Cannot add dynamic attributes after class definition.
16 What is the difference between __str__ and __repr__? OOP
__repr__ is for developers: unambiguous, ideally something that could reconstruct the object, and what you see in the REPL or a traceback. __str__ is for users: readable, what print() and str() give you. If you write only one, write __repr____str__ falls back to it, but not the other way round.
17 How do you make a class support == and use it in a set? OOP
Implement __eq__ for equality and __hash__ for hashing, over the same fields. Defining __eq__ alone sets __hash__ to None, making the class unhashable — that is Python protecting you from objects that compare equal but hash differently. @dataclass(frozen=True) generates both correctly, which is usually the right answer.
18 What is a property, and why not just use a public attribute? OOP
@property turns a method into a read that looks like an attribute, with an optional @x.setter. Start with a plain public attribute — Python has no need for Java-style getters. Reach for a property only when you later need validation, a computed value, or a deprecation shim, and the point is that you can add it without changing a single caller.
19 What is duck typing, and how do protocols fit in? OOP
Python dispatches on behaviour, not declared type: if an object has the method you call, it works. That is why functions take "something iterable" rather than a specific class. typing.Protocol makes that contract checkable — a static type describing the methods required, with no inheritance needed, so existing classes satisfy it retroactively.
20 What is the difference between a class attribute and an instance attribute? OOP
A class attribute lives on the class and is shared by every instance; an instance attribute is created per object, usually in __init__. Assigning through an instance creates an instance attribute that shadows the class one.
class Dog:
    tricks = []            # shared by every dog — the classic bug
    def __init__(self, name):
        self.name = name   # per instance

a, b = Dog("a"), Dog("b")
a.tricks.append("sit")
b.tricks               # ["sit"] — same list
21 What is the Diamond Problem in inheritance? How does Python solve it? OOP
The Diamond Problem occurs when a class inherits from two classes that both inherit from a common base — creating ambiguity about which path to follow.
text
      A
     / \
    B   C
     \ /
      D      ← Which A.__init__ does D call?
python
class A:
    def hello(self): print("A")

class B(A):
    def hello(self): print("B"); super().hello()

class C(A):
    def hello(self): print("C"); super().hello()

class D(B, C): pass

D().hello()        # B → C → A  (MRO order)
print(D.__mro__)   # (D, B, C, A, object)
Python's solution: C3 Linearization creates a consistent, deterministic MRO.
Rule of thumb: Always use super() in cooperative multiple inheritance so the MRO chain is properly followed.
22 What is composition? When should you prefer it over inheritance? OOP
Composition = "has-a" relationship (object contains other objects).
Inheritance = "is-a" relationship (child is a specialised parent).

python
# Inheritance: Car IS-A Vehicle
class Car(Vehicle): ...

# Composition: Car HAS-A Engine
class Engine:
    def start(self): print("Engine started")

class Car:
    def __init__(self):
        self.engine = Engine()   # composed

    def start(self):
        self.engine.start()
Prefer composition when:
  • You need to change behaviour at runtime (swap out the component)
  • Inheritance would create tight coupling
  • Multiple inheritance becomes complex or fragile
Principle: "Favor composition over inheritance" (Gang of Four) — more flexible, easier to test.
23 Explain the Singleton pattern and how to implement it in Python. OOP
Singleton ensures a class has only one instance and provides global access to it.
python
# Method 1: __new__
class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super().__new__(cls)
        return cls._instance

# Method 2: via Metaclass
class SingletonMeta(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super().__call__(*args, **kwargs)
        return cls._instances[cls]

# Verify
a, b = Singleton(), Singleton()
print(a is b)  # True
Use cases: Database connections, logging, configuration managers.
Caution: Singletons can make testing harder — consider dependency injection as an alternative.
24 What is the difference between shallow copy and deep copy in OOP? OOP
AspectShallow CopyDeep Copy
Top-level objectNew object createdNew object created
Nested objectsReferences copied (shared)Recursively duplicated
Mutation riskMutating nested obj affects bothFully independent
PerformanceFasterSlower (recursive)
python
import copy

class Address:
    def __init__(self, city): self.city = city

class Person:
    def __init__(self, addr): self.addr = addr

p1 = Person(Address("NYC"))
p2 = copy.copy(p1)      # shallow — p2.addr is p1.addr
p3 = copy.deepcopy(p1)  # deep   — p3.addr is a new object

p2.addr.city = "LA"
print(p1.addr.city)  # LA  ← shallow copy shares nested obj
print(p3.addr.city)  # NYC ← deep copy is independent
25 What are metaclasses in Python? OOP
A metaclass is the "class of a class" — it defines how classes themselves behave, just as classes define how instances behave.

type is the default metaclass for all Python classes. Custom metaclasses inherit from type.
python
# Every class is an instance of its metaclass
print(type(int))    # <class 'type'>
print(type(type))   # <class 'type'>

# Custom metaclass: enforce method naming convention
class EnforceLower(type):
    def __new__(mcs, name, bases, namespace):
        for key in namespace:
            if key.startswith('_'): continue
            if key != key.lower():
                raise TypeError(f"Method '{key}' must be lowercase")
        return super().__new__(mcs, name, bases, namespace)

class MyModel(metaclass=EnforceLower):
    def save(self): pass       # OK
    # def Save(self): pass   # → TypeError
Use sparingly: Metaclasses are powerful but add significant complexity. ORMs (like Django), API frameworks, and dataclasses use them internally.
26 What are the four main creational patterns, in one line each? OOP
Factory method: a method decides which subclass to build. Abstract factory: one object builds a whole family of related products. Builder: assemble a complex object step by step, so the constructor does not take twelve arguments. Prototype: clone an existing instance instead of constructing from scratch. All four exist to keep the choice of concrete class out of the calling code.
27 Explain the observer pattern and where you have already used it. OOP
One subject keeps a list of observers and notifies them when its state changes, so publishers know nothing about subscribers. You have used it every time you wrote addEventListener, subscribed to a store, or connected a signal. The trap is lifetime: an observer that never unsubscribes keeps the subject holding a reference to it, which is a leak.
28 What is the strategy pattern, and what does it replace? OOP
Interchangeable algorithms behind one interface, chosen at runtime. It replaces the growing if/elif chain that picks behaviour by type — each branch becomes its own object, and adding a case stops meaning editing the dispatcher. In Python a strategy is often just a function passed in; you do not need a class per algorithm.
29 What is dependency injection, and why does it matter for tests? OOP
Passing a collaborator in rather than constructing it inside. A class that builds its own database client can only ever be tested against a real database; one that accepts a client can be handed a fake. That is the whole benefit — it turns a hard dependency into a parameter, which is also what makes the dependency visible in the signature.
30 When is inheritance the wrong tool, and what are the symptoms? OOP
When the relationship is not genuinely is-a. Symptoms: a subclass overriding a method to raise NotImplementedError; a base class growing flags so it can behave differently per subclass; a hierarchy more than two or three deep; needing to know which subclass you have. Each of those is composition or a strategy wearing an inheritance costume.
No questions match your search.