Master the most asked OOPs concepts in technical and machine coding rounds. Covers 15–20% of typical interview weightage.
The four pillars are:
1) Encapsulation — bundling data and methods together, hiding internal state using access modifiers (private, protected, public).
2) Abstraction — hiding implementation details and showing only essential features (achieved via abstract classes/interfaces).
3) Inheritance — a class acquiring properties of another class, promoting code reuse.
4) Polymorphism — same interface behaving differently (compile-time via method overloading, runtime via method overriding).
A Class is a blueprint or template that defines attributes (fields) and behaviors (methods). An Object is an instance of a class — a concrete entity created in memory using the `new` keyword. Multiple objects can be created from one class, each with their own state. Example: 'Car' is a class; your specific car with plate number 'ABC123' is an object.
Inheritance allows a child class to inherit properties and methods from a parent class using the `extends` keyword. Types:
1) Single Inheritance — one parent, one child.
2) Multilevel — A→B→C.
3) Hierarchical — one parent, multiple children.
4) Multiple Inheritance — multiple parents (supported via interfaces in Java; causes Diamond Problem in C++ solved using virtual inheritance).
5) Hybrid — combination of above.
Polymorphism means 'many forms'. Compile-time (Static) Polymorphism is achieved through Method Overloading — same method name, different parameters, resolved at compile time. Runtime (Dynamic) Polymorphism is achieved through Method Overriding — child class provides a specific implementation of a parent's method, resolved at runtime using dynamic dispatch. Runtime polymorphism requires inheritance and the `@Override` annotation.
Encapsulation bundles data (fields) and methods that operate on that data into a single unit (class), and restricts direct access to internal state. Implemented using: private fields + public getter/setter methods. Benefits: data hiding, controlled access, code maintainability, and ability to validate data in setters. Example: A BankAccount class with a private `balance` field accessible only through `deposit()`, `withdraw()`, `getBalance()` methods.
Abstraction hides implementation details and exposes only what's necessary. Abstract Class: can have abstract and concrete methods, instance variables, constructors; a class can extend only one abstract class. Interface: only abstract methods (Java 8+ allows default/static methods), constants; a class can implement multiple interfaces. Use abstract class for 'is-a' relationship with shared code; use interface for 'can-do' capability (contract). Java interfaces support multiple inheritance.
Method Overloading (Compile-time Polymorphism): Same class, same method name, different parameter list (count, type, or order). Return type alone cannot differentiate. Example: `add(int a, int b)` and `add(double a, double b)`. Method Overriding (Runtime Polymorphism): Subclass redefines a parent's method with the same signature. Rules: cannot reduce visibility, cannot override final/static/private methods, return type must be same or covariant.
A Constructor is a special method called automatically when an object is created; same name as class, no return type. Types:
1) Default Constructor — provided by compiler if no constructor is defined.
2) Parameterized Constructor — accepts arguments.
3) Copy Constructor — creates an object by copying another (explicit in Java, implicit in C++). Constructor Chaining: calling one constructor from another using `this()` (same class) or `super()` (parent class) — must be the first statement.
Access Modifiers control visibility:
1) private — accessible only within the same class.
2) default (package-private) — accessible within the same package.
3) protected — accessible within the same package and subclasses.
4) public — accessible from anywhere. Best practice: make fields private (encapsulation) and expose functionality through public methods. In C++: public, protected, private (default is private for class, public for struct).
`this` refers to the current object instance. Uses:
1) Distinguish instance variables from parameters with same name.
2) Call another constructor in the same class (`this()`).
3) Pass current object as argument. `super` refers to the immediate parent class. Uses:
1) Access parent class methods/fields overridden in child.
2) Call parent class constructor (`super()` — must be first statement in child constructor).
3) Access parent class methods: `super.methodName()`.
Static members belong to the class, not instances — shared across all objects, accessed via class name. Non-static (instance) members belong to each specific object. Static methods cannot access non-static members directly (no `this` reference). Static variables are initialized once when the class loads. Use cases: static — utility methods (Math.sqrt), constants (PI), factory methods, singleton pattern. Non-static — object-specific state and behavior.
SOLID is an acronym for 5 OOP design principles: S — Single Responsibility Principle: a class should have only one reason to change. O — Open/Closed Principle: open for extension, closed for modification. L — Liskov Substitution Principle: objects of subclasses should be substitutable for parent class objects. I — Interface Segregation Principle: clients should not be forced to implement unused interfaces. D — Dependency Inversion Principle: depend on abstractions, not concretions.
Design Patterns are reusable solutions to common software design problems. Categories:
1) Creational — Singleton (one instance), Factory (object creation without specifying class), Builder (step-by-step object construction).
2) Structural — Adapter (incompatible interfaces), Decorator (add behavior dynamically), Facade (simplified interface).
3) Behavioral — Observer (publish-subscribe), Strategy (interchangeable algorithms), Command (encapsulate requests).
Singleton ensures only one instance of a class exists globally. Implementation: private constructor + private static instance + public `getInstance()` method. Thread-safe variants:
1) Synchronized method — simple but slow.
2) Double-checked locking with volatile — efficient.
3) Static inner class (Bill Pugh) — lazy initialization, thread-safe without synchronization.
4) Enum Singleton — simplest, handles serialization. Use cases: Database connection pool, Logger, Configuration manager.
An Abstract Class cannot be instantiated directly and may contain abstract methods (declared but not implemented). It serves as a base for subclasses that must implement the abstract methods. A Concrete Class provides implementations for all methods and can be instantiated. If a subclass does not implement all abstract methods, it must also be declared abstract. Abstract classes can have constructors, fields, and non-abstract methods for shared behavior.
Multiple inheritance allows a class to inherit from more than one parent class. Java avoids it for classes due to the Diamond Problem — if two parent classes define the same method and a child inherits both, which version does the child use? Java resolves this by: allowing multiple interface implementation (since interfaces had no state/implementation pre-Java 8), and using default methods with explicit override when conflict arises. C++ supports multiple inheritance using virtual inheritance to resolve Diamond Problem.
Inheritance models 'is-a' relationships (Dog is-a Animal). Composition models 'has-a' relationships (Car has-a Engine). Favor Composition over Inheritance (OOP principle) because: inheritance creates tight coupling and breaks encapsulation, changes to parent class ripple to children, and composition allows flexible swapping of behaviors at runtime. Example: Instead of `class Stack extends ArrayList`, use `class Stack { private ArrayList list; }` — cleaner and more maintainable.
An Interface defines a contract — a set of method signatures that implementing classes must provide. Key features: supports multiple implementation, all methods are implicitly public/abstract (Java 8+ allows default and static methods), all fields are public static final constants. Importance: enables polymorphism, loose coupling, dependency injection, and testability. Example: `Comparable`, `Serializable`, `Runnable` in Java. Program to interfaces, not implementations.
Exception Handling manages runtime errors gracefully using: try (code that may throw), catch (handles specific exceptions), finally (always executes), throw (manually throw an exception), throws (declares checked exceptions in method signature). Checked exceptions (compile-time): must be caught or declared (IOException, SQLException). Unchecked exceptions (runtime): need not be declared (NullPointerException, ArrayIndexOutOfBoundsException). Custom exceptions extend Exception or RuntimeException.
Shallow Copy copies the object's reference — both original and copy point to the same nested objects. Changes in nested objects are reflected in both. Deep Copy creates a fully independent copy — all nested objects are also copied. Modifications don't affect the original. In Java: `Object.clone()` performs shallow copy by default. Deep copy requires: overriding `clone()` and recursively copying fields, serialization/deserialization, or manual copy constructors. Immutable objects eliminate copy concerns.