Interview Questions · OOP

OOPs Interview Questions and Answers: 50 Questions That Actually Get Asked

From the four pillars to tricky output questions, with short answers you can say out loud and code that proves them. Built for campus placements and 1 to 8 years experienced interviews alike.

✍️ Pranjal Jain, Ex-Microsoft · IIT Kanpur 📅 10 October 2026 ⏱ 21 min read
Nested glass cubes containing gears, symbolising objects, classes and inheritance
TL;DR
  • 50 OOP questions grouped by topic, each with an answer short enough to say in an interview and code where code proves the point.
  • Most marks are lost on four distinctions: overloading vs overriding, abstract class vs interface, abstraction vs encapsulation, and inheritance vs composition.
  • Experienced candidates get probed on dynamic dispatch internals (vtables), Liskov violations, immutability and the equals/hashCode contract.
  • The seven tricky output questions at the end (static hiding, field hiding, constructor calling overridden methods, overload resolution with null) are the most common traps.

OOP questions appear in nearly every software interview in India: as a full technical round at TCS, Infosys, Wipro or Cognizant, as warm-up questions at product companies, and as the foundation under every low-level design round. The questions are predictable. What separates candidates is whether the answer sounds like a definition recited from notes or like someone who has actually written classes and hit the edge cases.

Answers below are written in the way you would say them, followed by code where a snippet settles the question. Examples are in Java (the most common interview language for OOP), with C++ and Python notes where the languages differ in an interview-relevant way.

How OOP Is Tested in Interviews

Freshers get definition questions plus "give a real example": what is polymorphism, show me overloading, why can't we instantiate an abstract class. Experienced engineers (2+ years) get "why" and "what breaks" questions: why composition over inheritance, how dynamic dispatch works, what happens if you override equals but not hashCode, design an immutable class. Both groups get output-prediction snippets.

💡
Answer formulaDefinition in one sentence, a concrete example from a real system (a payment, a vehicle, a notification), then one edge case or trade-off. Three sentences, done. Stop and let the interviewer pull further.

Four Pillars of OOPs: Questions 1 to 10

Q1. What is object-oriented programming?

A paradigm that models software as objects, each combining state (fields) and behaviour (methods), interacting through well-defined interfaces. The goal is to manage complexity: changes stay local to the object that owns the data, and new behaviour can be added by adding types rather than editing existing code.

Q2. What are the four pillars of OOP?

Encapsulation (bundle data with methods and restrict direct access), abstraction (expose what, hide how), inheritance (derive a type from another to reuse and specialise) and polymorphism (one interface, many implementations).

Q3. What is encapsulation? Give a real example.

Encapsulation hides internal state and forces all changes through methods that enforce invariants. A bank account should never have a negative balance, so balance is private and only deposit/withdraw can change it.

Java
public class BankAccount {
    private long balancePaise;               // hidden state

    public void deposit(long paise) {
        if (paise <= 0) throw new IllegalArgumentException("amount must be positive");
        balancePaise += paise;
    }
    public void withdraw(long paise) {
        if (paise > balancePaise) throw new IllegalStateException("insufficient funds");
        balancePaise -= paise;
    }
    public long getBalancePaise() { return balancePaise; }   // read-only view, no setter
}

Note the deliberate absence of setBalance. Private fields plus a public getter and setter for each one is not real encapsulation; it just adds ceremony around public fields.

Q4. What is abstraction?

Showing only essential behaviour and hiding implementation detail. A PaymentProcessor interface exposes pay(order); the caller does not know whether it talks to UPI, a card network or a wallet. In Java, abstraction is achieved with interfaces and abstract classes.

Q5. Abstraction vs encapsulation: what is the difference?

Abstraction is a design-level decision about the outside view (what operations exist). Encapsulation is an implementation-level mechanism to protect the inside (access modifiers, invariants). A TV remote is abstraction (buttons, not circuits); the sealed plastic case is encapsulation.

Q6. What is inheritance and what types exist?

A class acquires fields and methods of a parent and can override or extend them. Types: single, multilevel (A to B to C), hierarchical (many children of one parent), multiple (one child, many parents) and hybrid. Java supports multiple inheritance only through interfaces; C++ supports it for classes; Python supports it with a defined method resolution order (MRO).

Q7. What is polymorphism?

The ability of one interface to take many forms. Shape s = new Circle(); s.area(); calls Circle.area(), and the same line with a Square calls Square.area(). Types are covered in Q20.

Q8. What is the diamond problem and how do languages handle it?

If B and C both inherit from A and override hello(), and D inherits from both, which hello() does D get? Java forbids multiple class inheritance; with interfaces, if two default methods clash the class must override and may delegate explicitly. C++ uses virtual inheritance to share one A subobject and requires disambiguation. Python uses the C3 linearised MRO (D.__mro__).

Java
interface Walker  { default String move() { return "walk"; } }
interface Swimmer { default String move() { return "swim"; } }

class Duck implements Walker, Swimmer {
    @Override public String move() {               // compile error without this override
        return Walker.super.move() + " and " + Swimmer.super.move();
    }
}

Q9. What are access modifiers in Java?

ModifierSame classSame packageSubclass (other package)Everywhere
privateYesNoNoNo
default (none)YesYesNoNo
protectedYesYesYes (via inheritance)No
publicYesYesYesYes

C++ has private, protected, public (and friend). Python has no enforced privacy: _x is a convention and __x triggers name mangling to _ClassName__x.

Q10. What are coupling and cohesion?

Cohesion is how focused a class is on one responsibility; aim high. Coupling is how much a class depends on others' internals; aim low. A UserService that also formats invoices and sends SMS has low cohesion; a class calling order.getCustomer().getAddress().getCity() is tightly coupled to three structures. These two ideas underlie the SOLID principles.

Classes, Objects and Constructors: Questions 11 to 19

Q11. Class vs object?

A class is a blueprint (type definition); an object is an instance with its own state in memory. One Car class, many car objects. In Java the class's metadata lives in the method area (Metaspace), objects live on the heap.

Q12. What is a constructor and what types exist?

A special method that initialises a new object; it has the class name and no return type. Types: default (compiler-provided only if you write none), no-arg, parameterised, and in C++ a copy constructor (Java has no built-in copy constructor, though you can write one). Constructors can be overloaded but not overridden or inherited.

Q13. Can a constructor be private? Why would you do that?

Yes. Private constructors block outside instantiation, used in Singletons, static factory methods (List.of()), builders, and utility classes like java.lang.Math. See the design patterns guide for the thread-safe Singleton.

Q14. What are this and super?

this refers to the current object: used to disambiguate fields from parameters and to chain constructors (this(...)). super refers to the parent part: to call an overridden parent method (super.save()) or a parent constructor (super(...)). Traditionally this(...) or super(...) must be the first statement of a constructor; recent Java versions relax this slightly for statements that do not touch the object, but in interviews the first-statement rule is the expected answer.

Q15. What does the static keyword mean?

A static member belongs to the class, not to any instance. Static fields are shared by all objects (e.g., an instance counter); static methods cannot access instance members directly because there is no this. Static blocks run once when the class is initialised.

Q16. What is the difference between final, finally and finalize?

final: a variable cannot be reassigned, a method cannot be overridden, a class cannot be extended. finally: a block after try that runs whether or not an exception occurs. finalize(): an old GC hook, deprecated since Java 9 and marked for removal; use try-with-resources or Cleaner instead.

Q17. Shallow copy vs deep copy?

A shallow copy duplicates the outer object but shares referenced objects; a deep copy duplicates the whole graph. If Order holds a List<Item>, a shallow copy means modifying items in the copy changes the original. Object.clone() is shallow by default, which is one reason many style guides prefer copy constructors.

Q18. How do you design an immutable class?

  1. Declare the class final (or make constructors private with factories) so subclasses cannot add mutability.
  2. Make all fields private final.
  3. No setters.
  4. Defensively copy mutable inputs in the constructor and mutable outputs in getters.
Java
import java.util.List;

public final class Invoice {
    private final String id;
    private final List<String> lineItems;

    public Invoice(String id, List<String> lineItems) {
        this.id = id;
        this.lineItems = List.copyOf(lineItems);    // defensive, unmodifiable copy
    }
    public String getId() { return id; }
    public List<String> getLineItems() { return lineItems; } // already unmodifiable
}

Benefits: inherently thread-safe, safe as HashMap keys, easy to reason about. String, Integer and Java record types are immutable (records are shallowly immutable: a record holding a mutable list still needs a defensive copy).

Q19. What is the equals/hashCode contract?

If a.equals(b) then a.hashCode() == b.hashCode(). The reverse need not hold. Override equals without hashCode and two "equal" objects land in different HashMap buckets, so map.get(equalKey) returns null and a HashSet stores duplicates. This is a favourite experienced-level question; the HashMap internals guide explains the bucket mechanics.

Polymorphism Interview Questions: 20 to 28

Q20. What are the types of polymorphism?

TypeResolvedMechanismExample
Compile-time (static, ad-hoc)Compile timeMethod overloading, operator overloading (C++)add(int,int), add(double,double)
Runtime (dynamic, subtype)RuntimeMethod overriding + dynamic dispatchShape s = new Circle(); s.area()
ParametricCompile timeGenerics (Java), templates (C++)List<T>, std::vector<T>

Most interviewers only expect the first two; mentioning parametric polymorphism is a small bonus.

Q21. Overloading vs overriding?

OverloadingOverriding
WhereSame class (or inherited)Subclass redefines parent method
SignatureSame name, different parameter listSame name and parameters
Return typeCan differ (but alone cannot distinguish)Same or covariant (subtype)
BindingCompile time, on static typesRuntime, on actual object type
AccessAnyCannot be more restrictive
Checked exceptionsAnyCannot throw new or broader checked exceptions

Q22. Can we overload by return type alone?

No. int get() and String get() in one class is a compile error because a call like get(); gives the compiler no way to choose.

Q23. Can static, private or final methods be overridden?

None of them. Static methods are hidden, not overridden (resolved by reference type). Private methods are invisible to the subclass, so a same-named method in the child is a new, unrelated method. Final methods explicitly forbid overriding.

Q24. How does dynamic dispatch work internally?

Conceptually, each class has a virtual method table (vtable): an array of pointers to the method implementations for that class. Each object carries a pointer to its class's metadata. A virtual call looks up the slot for that method in the object's table and jumps there. C++ compilers implement exactly this, with a hidden vptr per object of a polymorphic class. The JVM uses similar tables, and the JIT often removes the indirection entirely through inlining when only one implementation has been loaded (monomorphic call sites).

Q25. Why must a base class destructor be virtual in C++?

If you delete a derived object through a base pointer and the base destructor is non-virtual, the behaviour is undefined; in practice only the base destructor runs and derived resources leak.

C++
#include <iostream>
#include <memory>

struct Base {
    virtual ~Base() { std::cout << "~Base\n"; }   // remove 'virtual' and ~Derived is skipped
};
struct Derived : Base {
    int* buf = new int[1024];
    ~Derived() override { delete[] buf; std::cout << "~Derived\n"; }
};

int main() {
    std::unique_ptr<Base> p = std::make_unique<Derived>();
}   // prints ~Derived then ~Base

Q26. What is object slicing?

In C++, assigning or passing a derived object by value as a base type copies only the base part; the derived part is "sliced off" and virtual calls on the copy hit the base implementation. Pass polymorphic objects by reference or pointer. Java has no slicing because objects are always handled through references.

Q27. What are upcasting and downcasting?

Upcasting (child to parent reference) is implicit and always safe. Downcasting (parent reference to child type) needs an explicit cast and throws ClassCastException if the object is not actually that type. Guard it with instanceof; Java 16+ pattern matching makes this concise: if (shape instanceof Circle c) { c.radius(); }. Frequent downcasting is a design smell: the behaviour probably belongs in an overridden method.

Q28. What is a covariant return type?

An overriding method may return a subtype of the parent's return type. If Animal.reproduce() returns Animal, Dog.reproduce() may return Dog. This avoids casts at the call site.

Abstract Class vs Interface: Questions 29 to 36

Q29. What is the difference between an abstract class and an interface?

AspectAbstract classInterface (Java 8+)
StateAny fields, including mutable instance fieldsOnly public static final constants
ConstructorsYes (called via super)No
MethodsAbstract and concrete, any access levelAbstract, default, static, and private helpers (Java 9+)
InheritanceA class extends only oneA class implements many
Models"Is-a" with shared code and state"Can-do" capability or contract
ExampleAbstractList, HttpServletComparable, Runnable, List

Q30. When would you choose an abstract class over an interface?

When subclasses share state and a fixed algorithm skeleton. Example: every report generator fetches data, formats it, and writes a header and footer. An abstract ReportGenerator holds the template (generate() calling abstract fetch() and format()), which is the Template Method pattern. Choose an interface when unrelated classes need a common capability (Comparable, AutoCloseable) or when you want multiple inheritance of type. A common modern combination is an interface for the contract plus an abstract base class for convenience, as the JDK does with List and AbstractList.

Q31. Can an abstract class have a constructor? Can it be instantiated?

It can have constructors, which initialise its fields when a subclass is created. It cannot be instantiated directly with new, although new Shape() { ... } creates an anonymous subclass, which is legal.

Q32. Can an abstract class have zero abstract methods?

Yes. Marking it abstract simply prevents instantiation. HttpServlet is abstract yet has no abstract methods; you are expected to override the ones you need.

Q33. Why were default methods added to interfaces?

For interface evolution. Java 8 needed to add stream() and forEach() to Collection without breaking every existing implementation in the world. Default methods provide a body that implementing classes inherit unless they override.

Q34. What is a marker interface?

An interface with no methods that tags a class for special treatment, such as Serializable and Cloneable. Annotations largely replaced the idea, but marker interfaces have one advantage: they define a type the compiler can check.

Q35. What is a functional interface?

An interface with exactly one abstract method, which lets you implement it with a lambda or method reference: Runnable, Comparator, Function<T,R>. @FunctionalInterface asks the compiler to enforce the single-method rule.

Q36. How is an interface done in C++ and Python?

C++: a class with only pure virtual functions (virtual void draw() = 0;) and a virtual destructor. Python: an abstract base class using abc.ABC and @abstractmethod, or structurally with typing.Protocol. Python also relies heavily on duck typing: if it has a read() method, it can be used as a file.

Inheritance vs Composition: Questions 37 to 43

Q37. What is composition over inheritance?

Build behaviour by holding references to other objects (has-a) instead of extending classes (is-a). Inheritance is the tightest coupling in OOP: the child depends on the parent's implementation details, and the relationship is fixed at compile time.

The classic JDK cautionary tale: java.util.Stack extends Vector. Because of that inheritance, a Stack exposes add(int index, E e) and get(i), letting callers insert into the middle of a stack, which breaks the abstraction. A composed stack would hold a list privately and expose only push, pop and peek. That is why Java recommends ArrayDeque for stacks.

Java
// Inheritance: a Logger hierarchy explodes as features combine
// FileLogger, TimestampedFileLogger, EncryptedTimestampedFileLogger...

// Composition: combine independent pieces at runtime
interface LogSink { void write(String line); }
interface LogFormatter { String format(String msg); }

class Logger {
    private final LogSink sink;
    private final LogFormatter formatter;
    Logger(LogSink sink, LogFormatter formatter) { this.sink = sink; this.formatter = formatter; }
    void log(String msg) { sink.write(formatter.format(msg)); }
}
// new Logger(line -> System.out.println(line), m -> java.time.Instant.now() + " " + m)

Q38. Association vs aggregation vs composition?

All are "has-a". Association: a general relationship (Teacher teaches Student). Aggregation: whole-part where the part can exist independently (a Team has Players; a disbanded team leaves players). Composition: whole-part with owned lifecycle (a House has Rooms; destroy the house, the rooms go). In UML, aggregation is a hollow diamond and composition a filled one.

Q39. What is the Liskov Substitution Principle? Give a violation.

Objects of a subclass must be usable wherever the parent is expected without breaking correctness. Classic violation: Square extends Rectangle. Code that calls setWidth(5); setHeight(4); and expects area 20 gets 16 from a Square, because Square must keep sides equal. Mathematically a square is a rectangle; behaviourally, a mutable Square is not a substitutable Rectangle. Fix: separate types implementing a common Shape, or make them immutable.

Q40. What is the fragile base class problem?

Changes to a parent class silently break subclasses. The textbook example (from Effective Java): a subclass of HashSet counts additions by overriding both add and addAll. Because HashSet.addAll internally calls add, each element is counted twice. The subclass depended on an implementation detail it could not see.

Q41. Is-a vs has-a: how do you decide in an LLD round?

Ask: "Is every X always a Y, everywhere a Y is used, for its whole life?" A Car is a Vehicle: inherit. A Car has an Engine that might be swapped for an ElectricMotor: compose. A Manager "is an" Employee today but could become an individual contributor tomorrow: model the role as a field, not a subclass.

Q42. What is method hiding vs overriding?

Static methods with the same signature in parent and child hide each other; which one runs depends on the reference type at compile time. Instance methods override; which one runs depends on the object at runtime. See tricky question Q44.

Q43. What is dependency injection and how does it relate to OOP?

Instead of a class constructing its collaborators (new MySqlRepo()), they are passed in, usually through the constructor, typed as interfaces. This is composition plus the Dependency Inversion Principle, and it makes classes testable with fakes. Spring and Guice automate the wiring, but plain constructor injection needs no framework.

Tricky OOPs Output Questions: 44 to 50

These snippets appear in written tests and live rounds. Predict the output before reading the answer.

Q44. Static method hiding vs instance overriding

Java
class A {
    void show() { System.out.println("A.show"); }
    static void hello() { System.out.println("A.hello"); }
}
class B extends A {
    @Override void show() { System.out.println("B.show"); }
    static void hello() { System.out.println("B.hello"); }
}
public class Main {
    public static void main(String[] args) {
        A a = new B();
        a.show();
        a.hello();
    }
}

Output: B.show then A.hello. Instance method: dynamic dispatch on the object (B). Static method: resolved by reference type (A). Compilers warn about calling static methods via instances for exactly this reason.

Q45. Fields are not polymorphic

Java
class Parent { String name = "parent"; String getName() { return name; } }
class Child extends Parent { String name = "child"; @Override String getName() { return name; } }

Parent p = new Child();
System.out.println(p.name + " " + p.getName());

Output: parent child. Field access uses the reference type; the method is dispatched to Child. The Child object actually contains two name fields. Field hiding is legal but confusing; avoid it.

Q46. Calling an overridden method from a constructor

Java
class Base {
    Base() { describe(); }
    void describe() { System.out.println("Base"); }
}
class Derived extends Base {
    private int x = 42;
    @Override void describe() { System.out.println("Derived x=" + x); }
}
new Derived();

Output: Derived x=0. The Base constructor runs before Derived's field initialisers, but dispatch already targets Derived, so it sees the default value 0. If x were an object it would be null, a classic source of NullPointerExceptions. Rule: never call overridable methods from constructors. (In C++ the same code prints Base, because during base construction the object's dynamic type is still Base.)

Q47. Overload resolution with null

Java
static void f(Object o) { System.out.println("Object"); }
static void f(String s) { System.out.println("String"); }
f(null);   // ?

static void g(String s)  { System.out.println("String"); }
static void g(Integer i) { System.out.println("Integer"); }
// g(null);  // ?

Answer: f(null) prints String because the compiler picks the most specific applicable overload, and String is a subtype of Object. g(null) does not compile: "reference to g is ambiguous", since neither String nor Integer is more specific.

Q48. Widening beats boxing

Java
static void h(long x)    { System.out.println("long"); }
static void h(Integer x) { System.out.println("Integer"); }
static void h(int... x)  { System.out.println("varargs"); }
h(5);

Output: long. Java resolves overloads in phases: first without boxing or varargs (widening int to long is allowed here), then with boxing, then with varargs. The first phase that finds a match wins.

Q49. Initialisation order with static and instance blocks

Java
class Parent {
    static { System.out.println("1 Parent static"); }
    { System.out.println("3 Parent instance block"); }
    Parent() { System.out.println("4 Parent constructor"); }
}
class Child extends Parent {
    static { System.out.println("2 Child static"); }
    { System.out.println("5 Child instance block"); }
    Child() { System.out.println("6 Child constructor"); }
}
new Child();
new Child();

Output: lines 1 to 6 in order for the first object, then only 3, 4, 5, 6 for the second. Static blocks run once at class initialisation (parent first). For each object, the parent's instance blocks and constructor complete before the child's.

Q50. C++ object slicing in action

C++
#include <iostream>
#include <string>

struct Animal {
    virtual std::string speak() const { return "..."; }
    virtual ~Animal() = default;
};
struct Dog : Animal {
    std::string speak() const override { return "Woof"; }
};

void byValue(Animal a)            { std::cout << a.speak() << "\n"; }
void byRef(const Animal& a)       { std::cout << a.speak() << "\n"; }

int main() {
    Dog d;
    byValue(d);   // ?
    byRef(d);     // ?
}

Output: ... then Woof. Passing by value copy-constructs an Animal, slicing away the Dog part, so the virtual call resolves to Animal::speak. Passing by reference preserves the dynamic type.

⚠️
Python twist interviewers likeIn Python, every method is effectively virtual and attributes are looked up at runtime on the instance first, then the class MRO. So the Q45 field-hiding result does not exist in Python: self.name always finds the instance attribute, which the most recent assignment set. Know which language your interviewer is assuming.

How to Prepare OOPs for Placements and Product Company Interviews

Reading 50 answers is not the same as being able to defend them under follow-ups. A focused plan:

  1. Day 1: say each pillar with an example from a real app. Practise out loud: encapsulation with a wallet balance, abstraction with a payment interface, inheritance with vehicle types, polymorphism with notification channels.
  2. Day 2: run every snippet in this post. Change one thing in each (remove virtual, make the method static, pass by value) and predict the new output first. This is how the tricky-output questions stop being tricky.
  3. Day 3: build one small system with interfaces. A parking lot or library management system in about 300 lines forces you to choose abstract class vs interface and inheritance vs composition for real. Use the library management LLD as a reference after attempting it.
  4. Day 4: connect to SOLID and patterns. Most experienced-level OOP questions are SOLID in disguise, and patterns are OOP applied to recurring problems. Skim the top 10 design patterns.
  5. Day 5: language-specific depth. For Java, the Java interview questions guide; for C++, the C++ interview questions guide, especially virtual functions, the rule of three/five and smart pointers.

Red flags interviewers notice

  • Defining polymorphism as "many forms" and stopping there, with no example.
  • Saying "interfaces cannot have method bodies" in a Java 8+ world.
  • Claiming encapsulation means "getters and setters for every field".
  • Using inheritance purely to reuse code (a Customer extends DatabaseConnection type of design).
  • Not knowing what breaks when hashCode is not overridden alongside equals.

Get these right and OOP becomes a round where you bank points rather than lose them, and it gives you a solid base for the LLD interview that follows at most product companies.

Frequently Asked Questions

What are the 4 pillars of OOPs?▾
Encapsulation, abstraction, inheritance and polymorphism. Encapsulation bundles data with the methods that guard it, abstraction exposes what an object does while hiding how, inheritance reuses and specialises a parent type, and polymorphism lets one interface have many implementations chosen at compile time or runtime.
What is the difference between abstraction and encapsulation?▾
Abstraction is a design idea about what to expose: a simple interface such as pay(amount) that hides complexity. Encapsulation is the mechanism that protects an object's internal state, typically private fields with controlled methods. Abstraction is about the outside view, encapsulation about guarding the inside.
Which OOPs questions are asked for freshers in campus placements?▾
Expect the four pillars with real examples, overloading vs overriding, abstract class vs interface, constructors and their types, access modifiers, static keyword, and one or two output-prediction questions. Service companies like TCS, Infosys and Wipro ask these in technical rounds, and product companies ask them as warm-ups.
Does Java support multiple inheritance?▾
Not of classes, to avoid ambiguity over inherited state and implementation. A class can implement multiple interfaces, so Java supports multiple inheritance of type. If two interfaces supply the same default method, the class must override it and can pick one with InterfaceName.super.method().
Why is composition preferred over inheritance?▾
Inheritance couples a subclass to its parent's implementation, so changes in the parent can break children and the hierarchy is fixed at compile time. Composition assembles behaviour from smaller objects behind interfaces, which is easier to test, swap and extend. Use inheritance only for a true is-a relationship that satisfies the Liskov Substitution Principle.
Can we override static methods in Java?▾
No. A static method with the same signature in a subclass hides the parent's method rather than overriding it. The call is resolved at compile time using the reference type, so Parent p = new Child(); p.staticMethod() runs the Parent version.
What is runtime polymorphism?▾
Runtime polymorphism, or dynamic dispatch, is when the method that runs is chosen by the actual object type at runtime rather than the reference type. In Java all non-static, non-private, non-final instance methods are virtual by default; in C++ you need the virtual keyword.

Go From OOP Basics to LLD Rounds

Prepflix's course connects OOP fundamentals to real low-level design problems, with mock interviews that probe exactly these follow-ups.

Explore the Prepflix Course →
Pranjal Jain
Pranjal Jain

Ex-Microsoft SDE · IIT Kanpur · Founder of Prepflix. Helps engineers crack startup and product company interviews across India.