OOP interview questions and oops interview questions appear in almost every software interview—from campus placements to senior system design loops. Panels want more than definitions: they expect you to explain encapsulation vs abstraction, defend composition over inheritance, walk through compile-time vs runtime polymorphism, and apply SOLID to a real class diagram. Java oops interview questions are especially common in India and enterprise hiring because Java remains the default teaching language for object-oriented design.
Below are 45 questions with elaborate answers; technical sections include a strong answer sample you can say aloud. This guide is language-aware but emphasizes Java where interviewers drill syntax (abstract, interface, access modifiers). For JVM and Java-specific depth beyond OOP, continue with Java interview questions part 1 and part 2. For C++ OOP and memory, see C and C++ interview questions. For Python's object model and duck typing, see Python developer interviews.
Tested on: Ubuntu 25.04 (Plucky Puffin); kernel 6.14.0-37-generic; OpenJDK 21.0.9 for polymorphism and composition demos.
Interview context and how to prepare
What do OOP interviews actually test?
OOP interviews test whether you can model problems as objects with clear responsibilities—not whether you can recite "four pillars" without context.
| Layer | What interviewers probe |
|---|---|
| Fundamentals | Class, object, encapsulation, abstraction |
| Relationships | Inheritance, composition, association |
| Polymorphism | Overloading, overriding, dynamic dispatch |
| Java OOPs | Access modifiers, abstract, interface, super |
| Design quality | Coupling, cohesion, SOLID |
| Patterns | Strategy, Factory, Observer, when to use |
| Scenarios | Parking lot, notification system, payment module |
| Role | Emphasis |
|---|---|
| Fresher / campus | Pillars, overloading vs overriding, modifiers |
| Mid-level | Composition, SOLID, one pattern with example |
| Senior / SDET | LSP violations, DIP in frameworks, OOD whiteboard |
OOP vs procedural programming — what is the difference?
| Aspect | Procedural | Object-oriented |
|---|---|---|
| Unit of design | Functions, procedures | Classes and objects |
| State | Often global or passed parameters | Encapsulated in objects |
| Reuse | Copy functions or libraries | Inheritance, composition, interfaces |
| Modeling | Step-by-step algorithms | Entities with behavior |
| Scaling teams | Globals and side effects hurt | Boundaries via classes and interfaces |
Procedural code is fine for scripts and small tools—see shell scripting interviews. OOP shines when many developers share a long-lived codebase with changing requirements.
What is a typical OOP interview loop?
| Round | Duration | Focus |
|---|---|---|
| Aptitude / screening | 30 min | Basics, four pillars, Java syntax |
| Technical — fundamentals | 45–60 min | Inheritance, polymorphism, abstract vs interface |
| Technical — design | 45–60 min | SOLID, patterns, composition |
| Live coding / OOD | 45–60 min | Class diagram, implement small hierarchy |
| Managerial | 30 min | Team practices, code review, refactoring stories |
Experienced loops expect you to connect pillars, SOLID, and patterns to real class design—not recite definitions alone.
What is a realistic 3–5 week OOP prep plan?
| Week | Focus | Output |
|---|---|---|
| 1 | Four pillars + class diagrams | Explain each with one example |
| 2 | Inheritance, composition, polymorphism | Runnable Java demos |
| 3 | Abstract class vs interface, Java modifiers | Cheat sheet you can draw |
| 4 | SOLID + 3 patterns | One pattern per creational/behavioral |
| 5 | OOD scenarios + mock | Whiteboard parking lot or library |
Draw UML-style boxes on paper—interviewers reward clear entity relationships.
How does OOP differ across Java, Python, and C++?
| Feature | Java | Python | C++ |
|---|---|---|---|
| Model | Class-based, single inheritance | Class + duck typing | Multiple inheritance allowed |
| Encapsulation | private, protected, public |
Convention _name, __name |
private, protected, public |
| Abstraction | abstract class, interface |
ABC module, protocols (3.8+) | Pure virtual classes |
| Polymorphism | Overload + override | Duck typing + override | Virtual functions, templates |
| Memory | GC | GC | Manual / RAII |
Java oops interview questions focus on modifiers and interfaces. Python interviews stress duck typing—see Python interviews. C++ adds multiple inheritance and vtables—see C and C++ interviews.
Four pillars and core concepts
What are the four pillars of OOP?
| Pillar | Meaning | Example |
|---|---|---|
| Encapsulation | Bundle data + methods; control access | private balance + deposit() |
| Abstraction | Expose what, hide how | PaymentGateway.charge() hides PCI details |
| Inheritance | Reuse via IS-A | SavingsAccount extends Account |
| Polymorphism | One interface, many behaviors | Shape.draw() for Circle vs Square |
The pillars work together: encapsulation protects state, abstraction simplifies usage, inheritance shares structure, polymorphism lets callers depend on supertypes.
A strong answer is:
I name all four and immediately ground each in code—private fields for encapsulation, an interface for abstraction, extends for inheritance, and overriding draw() for polymorphism.
What is the difference between a class and an object?
| Term | Definition |
|---|---|
| Class | Blueprint—fields, methods, constructors |
| Object | Runtime instance created from a class |
| Instance | Synonym for object in many interviews |
class Dog {
String name;
void bark() { System.out.println("woof"); }
}
Dog rex = new Dog(); // rex is an object (instance) of class DogOne class → many objects (new Dog() twice yields two instances with separate state).
A strong answer is:
A class is the template; an object is a concrete instance at runtime with its own field values—one
Carclass, manyCarobjects in a fleet.
What is encapsulation?
Encapsulation binds data and methods that operate on that data into one unit (usually a class) and restricts direct access to internal state.
Benefits:
- Invariant protection — balance cannot go negative if
withdrawvalidates - Refactoring freedom — change internal representation without breaking callers
- Security — sensitive fields not public
public class BankAccount {
private int balance;
public void deposit(int amount) {
if (amount > 0) balance += amount;
}
public int getBalance() { return balance; }
}A strong answer is:
Encapsulation keeps state private and exposes behavior through methods so invariants stay enforced—I never let callers set
balancedirectly if rules matter.
What is abstraction?
Abstraction hides implementation complexity and shows only essential behavior—the "what" without the "how."
| Mechanism | Role |
|---|---|
| Abstract class | Partial implementation + shared code |
| Interface | Contract only—no implementation (pre-Java 8) |
| Public API | Service method names hide database/HTTP details |
Driving a car: you use accelerate()—not spark-plug timing. That is abstraction at the human level; in code, List abstracts whether backing store is array or linked nodes.
A strong answer is:
Abstraction is the simplified surface—an interface or abstract API—so callers depend on capabilities like charge() without knowing Stripe vs PayPal wiring.
Encapsulation vs abstraction — what is the difference?
| Encapsulation | Abstraction | |
|---|---|---|
| Focus | Protecting data | Hiding complexity |
| Level | Implementation (how data is guarded) | Design (what you expose) |
| Mechanism | private fields, getters |
Interfaces, abstract classes |
| Question answered | "Who can touch this state?" | "What can this thing do?" |
You can encapsulate without strong abstraction (public getters for everything). You can abstract without strict encapsulation (leaky interface returning internals).
A strong answer is:
Encapsulation guards state with access control; abstraction hides how work is done behind a simpler contract—I need both, but they answer different design questions.
What is data hiding and how does it relate to encapsulation?
Data hiding restricts visibility of fields using access modifiers (private, protected).
| Concept | Scope |
|---|---|
| Encapsulation | Broader—bundling data + behavior |
| Data hiding | Narrower—visibility of fields |
Encapsulation can exist with public fields (weak hiding). Production code should hide data and expose behavior.
A strong answer is:
Data hiding is the access-modifier part of encapsulation—I use private fields so internal representation can change without breaking every caller.
What is inheritance?
Inheritance lets a child class acquire fields and methods from a parent class—an IS-A relationship.
class Animal {
void eat() { System.out.println("eating"); }
}
class Dog extends Animal {
void bark() { System.out.println("woof"); }
}Benefits: reuse, polymorphism (treat Dog as Animal). Risks: tight coupling, fragile base class, deep trees—often replaced by composition for HAS-A.
A strong answer is:
Inheritance models IS-A reuse and enables overriding; I avoid deep trees and prefer composition when behavior is shared but not a true subtype relationship.
What is polymorphism?
Polymorphism ("many forms") lets one interface or superclass reference invoke different implementations depending on the actual object type.
Two forms in Java:
| Type | Mechanism | Binding |
|---|---|---|
| Compile-time | Method overloading | Static |
| Runtime | Method overriding | Dynamic |
interface Notifier {
String send(String message);
}
class EmailNotifier implements Notifier {
public String send(String message) { return "email:" + message; }
}
class SmsNotifier implements Notifier {
public String send(String message) { return "sms:" + message; }
}
public class PolymorphismDemo {
static String notifyUser(Notifier n, String msg) {
return n.send(msg);
}
public static void main(String[] args) {
System.out.println(notifyUser(new EmailNotifier(), "hello"));
System.out.println(notifyUser(new SmsNotifier(), "hello"));
}
}The same notifyUser method accepts any Notifier; runtime dispatch picks email: vs sms: output.
A strong answer is:
Polymorphism lets me code to Notifier or Shape supertypes and plug in Email or Circle implementations—compile-time overloading for convenience, runtime overriding for extensibility.
Inheritance, composition, and relationships
What are the types of inheritance?
| Type | Structure | Example |
|---|---|---|
| Single | One parent | Dog extends Animal |
| Multilevel | Chain | GoldenRetriever extends Dog extends Animal |
| Hierarchical | Many children, one parent | Cat, Dog extend Animal |
| Multiple | Several parents | C++ yes; Java classes no |
| Hybrid | Combination | Mix of hierarchical + multiple (via interfaces in Java) |
Java classes: single inheritance of classes, multiple interface implementation.
A strong answer is:
Java gives single class inheritance and multiple interfaces—I describe multilevel and hierarchical with Animal examples and mention C++ for true multiple inheritance contrast.
Composition vs inheritance — when do you choose each?
| Inheritance (IS-A) | Composition (HAS-A) | |
|---|---|---|
| Relationship | Subtype | Contains / uses |
| Coupling | Tight to parent | Looser—swap parts |
| Flexibility | Fixed at compile hierarchy | Inject strategies at runtime |
| Risk | Fragile base class | Slightly more boilerplate |
class Engine {
String start() { return "vroom"; }
}
class Car {
private final Engine engine = new Engine();
String drive() { return engine.start(); }
}
public class CompositionDemo {
public static void main(String[] args) {
System.out.println(new Car().drive());
}
}Favor composition when behavior varies or lifetime is HAS-A. Use inheritance for genuine taxonomic subtyping and shared interface contracts.
A strong answer is:
I default to composition for reusable behavior—Car has Engine—and reserve inheritance for true IS-A subtypes where Liskov substitution holds.
Aggregation vs composition vs association?
| Relationship | Ownership | Lifetime |
|---|---|---|
| Association | Uses | Independent |
| Aggregation | Weak HAS-A | Part can outlive whole |
| Composition | Strong HAS-A | Part dies with whole |
Example: Professor associated with University; Department aggregates Professor (professor can transfer); House composes Room (no house, no those rooms as part of that house).
A strong answer is:
Composition is strict ownership—engine with car; aggregation is looser—students with university; association is mere usage—a doctor and hospital.
IS-A vs HAS-A — explain with examples.
| Relation | Keyword in design | Example |
|---|---|---|
| IS-A | extends / implements |
ElectricCar IS-A Car |
| HAS-A | Field reference | Car HAS-A Engine |
Interview trap: modeling Stack extends ArrayList IS-A wrong for behavior—Stack HAS-A list (composition) avoids LSP violations.
A strong answer is:
IS-A for subtype polymorphism; HAS-A when one object contains or uses another—I rejected Stack extends ArrayList because a stack is not an array list behaviorally.
What is the diamond problem in multiple inheritance?
When class D inherits B and C, and both B and C inherit A and override the same method, D faces ambiguous which override to use:
A
/ \
B C
\ /
DJava avoids multiple class inheritance to prevent this. C++ allows it with virtual inheritance. Java uses interfaces + explicit default-method resolution.
A strong answer is:
Diamond ambiguity is why Java disallows extending two classes—I use interfaces and, if two defaults collide, override explicitly in the implementing class.
How does Java achieve multiple inheritance without extending two classes?
A class may:
class PaymentService implements Auditable, Retryable, MetricsAware { }Interfaces define contracts; a class implements many. Since Java 8, default methods on interfaces share implementation—but conflicting defaults require an override in the class.
A strong answer is:
Java gives multiple inheritance of type through interfaces, not multiple class extension—default methods add shared code with explicit conflict rules.
Method overloading vs method overriding?
| Overloading | Overriding | |
|---|---|---|
| Same name | Yes, different parameters | Yes, same signature in child |
| Class | Same class (or inherited) | Parent-child |
| Polymorphism | Compile-time (static) | Runtime (dynamic) |
| Return type | Can differ if params differ | Covariant returns allowed |
| Access | Any | Cannot reduce visibility |
class Calc {
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; } // overload
}
class Parent { String greet() { return "hi"; } }
class Child extends Parent {
@Override String greet() { return "hello"; } // override
}A strong answer is:
Overloading is same method name, different parameters, resolved at compile time; overriding is subclass replacing parent behavior, resolved at runtime via dynamic dispatch.
Polymorphism, abstraction, and Java types
What is compile-time (static) polymorphism?
Achieved through method overloading and operator overloading (C++, not Java).
Compiler picks the method at compile time based on argument types:
class Printer {
void print(int x) { System.out.println("int:" + x); }
void print(String s) { System.out.println("str:" + s); }
}
public class StaticPoly {
public static void main(String[] args) {
Printer p = new Printer();
p.print(42);
p.print("hi");
}
}Running prints int:42 then str:hi—the compiler bound each call statically.
A strong answer is:
Compile-time polymorphism is overloading—the compiler selects the method signature before the program runs; Java doesn't overload operators like C++.
What is runtime (dynamic) polymorphism?
Achieved through method overriding: reference type is superclass/interface; actual object type decides which method runs.
JVM uses virtual method tables (vtables) for instance methods. final, static, and private methods do not participate in runtime override dispatch the same way.
A strong answer is:
Runtime polymorphism is overriding—a variable typed as Animal holding a Dog calls Dog's speak() at runtime because dispatch uses the object's actual class.
What are upcasting and downcasting?
| Cast | Direction | Safety |
|---|---|---|
| Upcasting | Child → parent | Implicit, always safe |
| Downcasting | Parent → child | Explicit, can fail |
Animal a = new Dog(); // upcast (implicit)
Dog d = (Dog) a; // downcast — ClassCastException if wrong
if (a instanceof Dog dog) { // Java 16+ pattern matching
dog.bark();
}Always instanceof before downcasting in production code.
A strong answer is:
Upcast to general types for polymorphism; downcast only after instanceof check—otherwise I risk ClassCastException when the object isn't really that subtype.
What is an abstract class?
An abstract class cannot be instantiated; it may contain abstract methods (no body) and concrete methods.
abstract class Shape {
abstract double area();
void label() { System.out.println("shape"); }
}Use when subtypes share common state or implementation but need specialized behavior.
A strong answer is:
Abstract classes are partial blueprints—I share code and fields in Shape while forcing Circle to implement area().
What is an interface?
An interface defines a contract—method signatures that implementing classes must provide.
interface Persistable {
void save();
void delete();
}
class User implements Persistable {
public void save() { /* ... */ }
public void delete() { /* ... */ }
}Java 8+ allows default and static methods on interfaces. Interfaces support multiple implementation per class.
A strong answer is:
Interfaces define what a type can do without dictating inheritance tree—I implement several on one service class for cross-cutting contracts.
Abstract class vs interface — when do you use each?
| Factor | Abstract class | Interface |
|---|---|---|
| Instantiation | No | No |
| Multiple inherit | One class only | Many interfaces |
| State | Can have instance fields | Fields are public static final only |
| Constructors | Yes | No |
| Evolution | Adding method can break children | Default methods ease addition |
| Use when | Shared code + IS-A base | Capability contract |
Java 8+ blurs the line with default methods—still prefer interface for roles, abstract class for shared base implementation.
A strong answer is:
Interface for capabilities (Comparable, Runnable); abstract class when subclasses share fields and helper methods—I don't use abstract class just to block instantiation; use private constructor instead.
Java OOPs specifics
Explain Java access modifiers.
| Modifier | Class | Package | Subclass | World |
|---|---|---|---|---|
private |
Yes | No | No | No |
| (default) | Yes | Yes | No | No |
protected |
Yes | Yes | Yes | No |
public |
Yes | Yes | Yes | Yes |
Interview tip: protected exposes to subclasses even across packages—can leak API surface; prefer private + public methods.
A strong answer is:
I default to private fields, public behavior methods, and protected only when subclasses genuinely need hooks—package-private for internal module APIs.
What does final mean for class, method, and variable?
| Use | Effect |
|---|---|
final class |
Cannot be extended |
final method |
Cannot be overridden |
final variable |
Assign once (constant reference) |
String is final—security and immutability. Use final on method parameters and local variables when values should not be reassigned (readability).
A strong answer is:
final class blocks inheritance—String uses that; final method freezes behavior; final field means one assignment for references, which helps immutability when the object itself is immutable.
Static vs instance members in OOP?
| Instance | Static | |
|---|---|---|
| Belongs to | Each object | Class |
| Access | Needs object (or this) |
Class name |
| Override | Yes (polymorphism) | No—hiding only |
| Use | Per-object state | Constants, factories, counters |
Static methods cannot access instance fields directly. Overuse of static hurts testability and OOP boundaries—see also Java part 1 static questions.
A strong answer is:
Instance members carry per-object state; static belongs to the class—I avoid static mutable state because it breaks encapsulation and makes tests order-dependent.
What types of constructors exist in Java?
| Type | Description |
|---|---|
| Default | No-arg; compiler-generated if none defined |
| Parameterized | Takes arguments to initialize fields |
| Copy | Not built-in; write constructor copying fields |
| Chained | this(...) calls another constructor |
Rules: if any constructor is defined, default is not auto-generated. Subclass must call super(...) if parent has no no-arg constructor.
A strong answer is:
I use parameterized constructors for required fields and add explicit no-arg only when frameworks need it—remembering Java removes the default once I define any constructor.
What are this and super in Java?
| Keyword | Refers to | Common use |
|---|---|---|
this |
Current object | Field disambiguation, this() chaining |
super |
Parent class | super() constructor, super.method() |
class Employee extends Person {
Employee(String name, int id) {
super(name);
this.id = id;
}
}A strong answer is:
this is the current instance; super reaches the parent—constructor chaining must put super() or this() first line in constructors.
What are default methods on interfaces (Java 8+)?
interface Logger {
void log(String msg);
default void logInfo(String msg) { log("INFO: " + msg); }
}Allows evolving interfaces without breaking every implementor—implementors inherit default unless they override.
Conflict rule: if two interfaces provide the same default, the class must override and choose.
A strong answer is:
Default methods let me add behavior to interfaces without forcing every implementor to update—if two defaults clash, I override explicitly in the class.
Coupling, cohesion, and SOLID
What are coupling and cohesion?
| Metric | Good | Bad |
|---|---|---|
| Cohesion | Class does one focused job | God class does everything |
| Coupling | Classes depend on abstractions | Classes reach into each other's internals |
High cohesion + low coupling = easier tests and refactors. OOP tools: interfaces, composition, package-private boundaries.
A strong answer is:
I want high cohesion inside a class and loose coupling between classes—depending on PaymentGateway interface, not StripeClient concrete type.
What are the SOLID principles?
| Letter | Principle | One line |
|---|---|---|
| S | Single Responsibility | One reason to change |
| O | Open/Closed | Open for extension, closed for modification |
| L | Liskov Substitution | Subtypes must work wherever parent worked |
| I | Interface Segregation | Small interfaces |
| D | Dependency Inversion | Depend on abstractions |
SOLID guides maintainable OOP—common in mid/senior loops and Spring Boot design discussions.
A strong answer is:
SOLID keeps classes focused, extensible without edits, substitutable, interface-small, and wired to abstractions—I cite one real refactor per letter when pressed.
Explain Single Responsibility Principle (SRP).
A class should have only one reason to change—one axis of responsibility.
Bad: Invoice generates PDF, sends email, and calculates tax.
Better: Invoice, PdfRenderer, Mailer, TaxCalculator collaborate.
SRP improves testability—mock mailer without touching tax math.
A strong answer is:
SRP means one job per class—if email templates and tax rules change for different reasons, they belong in different classes, not one InvoiceGod.
Explain Open/Closed Principle (OCP).
Software entities should be open for extension, closed for modification—add behavior without editing stable code.
Pattern: Strategy — new DiscountStrategy class instead of editing checkout() switch:
interface DiscountStrategy { int apply(int total); }
class TenPercent implements DiscountStrategy {
public int apply(int total) { return total * 90 / 100; }
}A strong answer is:
OCP means I extend with new strategy or handler classes instead of patching a growing if-else in the core checkout method every time marketing adds a promo.
Explain Liskov Substitution Principle (LSP).
Subtypes must be substitutable for base types without breaking correctness.
Classic violation: Square extends Rectangle—setting width should not break square invariants.
// Anti-pattern: Square changes independent width/height semantics
class Square extends Rectangle {
void setWidth(int w) { super.setWidth(w); super.setHeight(w); }
}Callers expecting Rectangle behavior get surprises—favor composition over forced inheritance.
A strong answer is:
LSP means any Rectangle reference should behave as callers expect—Square-as-Rectangle violates that, so I model Square independently or use composition.
Explain Interface Segregation and Dependency Inversion.
ISP: Clients should not depend on methods they do not use.
// Bad: force read-only repo to implement delete()
interface Repository { void save(); void delete(); }
// Better: split
interface Writer { void save(); }
interface Deleter { void delete(); }DIP: High-level modules depend on abstractions, not concretions.
class OrderService {
private final PaymentGateway gateway; // interface
OrderService(PaymentGateway gateway) { this.gateway = gateway; }
}Spring dependency injection embodies DIP—see Spring Boot interviews.
A strong answer is:
ISP splits fat interfaces so implementors aren't forced to stub unused methods; DIP injects PaymentGateway interfaces into services so tests swap fakes without changing OrderService.
Design patterns and object-oriented design
Explain creational patterns: Singleton, Factory, Builder.
| Pattern | Purpose | Interview caution |
|---|---|---|
| Singleton | One instance | Hidden global state; prefer DI |
| Factory Method | Delegate object creation to subclass/factory | Decouples caller from concrete class |
| Builder | Step-by-step complex object construction | Lombok @Builder, StringBuilder |
interface Notification { void send(); }
class NotificationFactory {
static Notification create(String type) {
return switch (type) {
case "email" -> new EmailNotification();
default -> new SmsNotification();
};
}
}A strong answer is:
Factory hides concrete types; Builder assembles complex objects; Singleton only when one instance is truly required—I prefer Spring-scoped beans over hand-rolled Singletons.
Explain Strategy and Observer patterns.
Strategy: Encapsulate interchangeable algorithms—payment methods, compression codecs.
Observer: One-to-many notification—UI listeners, domain events.
interface PayStrategy { void pay(int cents); }
class Checkout {
private PayStrategy strategy;
void setStrategy(PayStrategy s) { strategy = s; }
void checkout(int cents) { strategy.pay(cents); }
}Strategy supports OCP—add CryptoPay without editing Checkout internals.
A strong answer is:
Strategy swaps algorithms at runtime—checkout doesn't care Visa vs UPI; Observer decouples event publishers from subscribers like order-placed emails.
Explain Adapter and Decorator patterns.
| Pattern | Role | Example |
|---|---|---|
| Adapter | Wrap incompatible API to match expected interface | Legacy LegacyPayment → PaymentGateway |
| Decorator | Add behavior without subclass explosion | BufferedInputStream wrapping FileInputStream |
Decorator avoids subclassing every combination of features; Adapter integrates third-party libraries into your OOP boundaries.
A strong answer is:
Adapter makes legacy APIs fit my interface; Decorator layers behavior—Java I/O streams are the textbook Decorator example I cite in interviews.
How would you design a parking lot system using OOP?
Entities (interview whiteboard approach):
| Class | Responsibility |
|---|---|
ParkingLot |
Floors, entry/exit, availability |
ParkingFloor |
Spots collection |
ParkingSpot |
Size, occupied, vehicle |
Vehicle |
Car, Truck, Motorcycle (type enum or subclass) |
Ticket |
Entry time, spot id |
PricingStrategy |
Interface — hourly, flat |
Use composition: lot HAS floors HAS spots. Use Strategy for pricing. Avoid one ParkingLotManager God class doing payment + SMS + spot math.
A strong answer is:
I'd identify entities, assign SRP, use Strategy for pricing and composition for floor-spot hierarchy, and keep entry/exit flows as methods on ParkingLot delegating to spot allocation—not a single static util class.
What are common OOP anti-patterns?
| Anti-pattern | Problem |
|---|---|
| God object | One class knows everything |
| Anemic domain | Data classes, logic in services only |
| Deep inheritance | Fragile overrides |
| Yo-yo problem | Jump many levels for one method |
| Premature pattern | Factory for one implementation |
Refactor toward small cohesive classes and composition.
A strong answer is:
God classes and deep inheritance hierarchies are red flags—I split responsibilities and inject strategies instead of adding another override layer.
OOP vs functional programming — how do they compare?
| OOP | Functional |
|---|---|
| State in objects | Immutable data, pure functions |
| Behavior via methods | Behavior via functions |
| Polymorphism | Higher-order functions |
| Java, C++, Python classes | Haskell, parts of Java streams |
Modern Java blends both—stream().map().filter() is functional style on collections; domain models remain OOP. Neither replaces the other in most enterprise codebases.
A strong answer is:
I use OOP for domain entities with lifecycle and functional style for transformations on immutable data—Java streams don't mean I abandon encapsulation in core models.
What should you rehearse before an OOP interview?
Checklist:
- Four pillars with one example each
- Encapsulation vs abstraction and data hiding
- Overloading vs overriding + compile vs runtime poly
- Composition vs inheritance + IS-A vs HAS-A
- Abstract class vs interface decision tree
- Diamond problem and Java interfaces
- Access modifiers table
- SOLID — all five with examples
- Two patterns — Strategy + Factory or Observer
- One OOD scenario — parking lot or library
- Java part 1 for Java-only follow-ups
- C and C++ if systems role
A strong answer is:
I whiteboard pillars and SOLID, run through overloading vs overriding aloud, and walk one OOD scenario with composition and Strategy—then tie answers to code I've actually written.
Pattern cheat sheet (quick reference)
| Need | OOP approach |
|---|---|
| Hide state | Encapsulation + private fields |
| Hide complexity | Abstraction / interface |
| Reuse IS-A behavior | Inheritance (carefully) |
| Reuse HAS-A behavior | Composition |
| Swap algorithms | Strategy pattern |
Create objects without new everywhere |
Factory |
| Many optional features | Decorator or composition |
| Notify many listeners | Observer |
| One class, one job | SRP |
| Extend without editing core | OCP + Strategy |
| Safe subtyping | LSP |
| Testable wiring | DIP + interfaces |
References
Object-oriented design
On-site prep
- Java interview questions (part one)
- Java interview questions (part two)
- C and C++ interview questions
- Python developer interviews
- Spring Boot interview questions
- Selenium interview questions
- Full stack developer interviews
- Interview Questions category
Summary
OOP interviews test whether you can explain why encapsulation and polymorphism matter, when composition beats inheritance, and how SOLID shows up in real code—not recite four pillar names from memory. Use this guide as a self-test: answer aloud and run the polymorphism and composition demos. Pair with Java interviews for language follow-ups and C and C++ interviews when memory and multiple inheritance come up.

