OOP
Encapsulation, Polymorphism, Inheritance, Abstraction, Design Principles & Patterns
OOP Fundamentals#
What is OOP?#
Answer:
Object-Oriented Programming (OOP) is a programming paradigm that organizes software around objects, which contain both data (fields/properties) and behavior (methods/functions).
The main goal of OOP is to improve:
- Code Reusability
- Maintainability
- Scalability
- Modularity
Example
class Car { String color; void drive() { System.out.println("Driving..."); }}
Here:
Car→ Classcolor→ State/Datadrive()→ Behavior- Actual car instance → Object
Interview Follow-up
Q: What are the four pillars of OOP?
- Encapsulation
- Abstraction
- Inheritance
- Polymorphism
Classes and Objects#
What is a Class?#
Answer:
A class is a blueprint or template that defines the properties and behaviors of objects.
Example
class Student { String name; int age;}
No memory is allocated for instance variables until an object is created.
What is an Object?#
Answer:
An object is a runtime instance of a class.
Example
Student s1 = new Student();
Here:
Student→ Classs1→ Object
Interview Follow-up
Q: Where is an object stored?
Objects are typically stored in Heap Memory.
Reference variables are stored in Stack Memory.
Encapsulation#
What is Encapsulation?#
Answer:
Encapsulation is the process of wrapping data and methods together into a single unit and restricting direct access to internal data.
Example
class Employee { private int salary; public int getSalary() { return salary; } public void setSalary(int salary) { this.salary = salary; }}
Benefits
- Data Security
- Better Maintainability
- Controlled Access
Interview Trap
Q: Is Encapsulation the same as Data Hiding?
No.
- Encapsulation = Wrapping data + methods
- Data Hiding = Restricting access
Data Hiding is achieved using Encapsulation.
Abstraction#
What is Abstraction?#
Answer:
Abstraction means hiding implementation details and exposing only essential functionality.
Real-Life Example
When driving a car:
You know how to use:
- Steering
- Brake
- Accelerator
But you don't know the internal engine implementation.
How is Abstraction achieved in Java?#
Using:
- Abstract Classes
- Interfaces
What is an Abstract Class?#
Answer:
A class declared using the abstract keyword.
It cannot be instantiated directly.
abstract class Vehicle { abstract void start();}
Can an Abstract Class have Constructors?#
Answer:
Yes.
Constructors are executed when child objects are created.
abstract class Vehicle { Vehicle() { System.out.println("Vehicle Constructor"); }}
Interview Trap
Q: Can we create an object of an abstract class?
No.
Vehicle v = new Vehicle(); // Compile Error
Interfaces#
What is an Interface?#
Answer:
An interface defines a contract that implementing classes must follow.
interface Payment { void pay();}
class CreditCardPayment implements Payment { public void pay() { System.out.println("Paid"); }}
Why do we use Interfaces?#
- Achieve Abstraction
- Achieve Multiple Inheritance
- Loose Coupling
- Better Testing
Abstract Class vs Interface#
| Feature | Abstract Class | Interface |
|---|---|---|
| Constructor | ✅ | ❌ |
| State | ✅ | ❌ |
| Multiple Inheritance | ❌ | ✅ |
| Methods with body | ✅ | ✅ (default/static) |
Interview Answer
Use:
- Abstract Class → When classes share common state/behavior
- Interface → When classes share only behavior
Inheritance#
What is Inheritance?#
Answer:
Inheritance allows one class to acquire properties and methods of another class.
class Animal { void eat() {}}class Dog extends Animal {}
Dog automatically gets access to eat().
Benefits#
- Code Reusability
- Reduced Duplication
- Better Organization
Types of Inheritance#
Single
A -> B
Multilevel
A -> B -> C
Hierarchical
A / \ B C
Multiple
A + B -> C
(Java supports this only via interfaces.)
Why doesn't Java support Multiple Inheritance with Classes?#
Because of the Diamond Problem.
Example:
class A { void show(){}}class B extends A {}class C extends A {}class D extends B, C {} // Ambiguous
Compiler won't know which show() to call.
Polymorphism#
What is Polymorphism?#
Answer:
Polymorphism means one entity taking multiple forms.
Two types:
- Compile-Time Polymorphism
- Runtime Polymorphism
Compile-Time Polymorphism#
Achieved using Method Overloading.
class MathUtil { int add(int a, int b) { return a + b; } int add(int a, int b, int c) { return a + b + c; }}
Compiler decides which method to call.
Runtime Polymorphism#
Achieved using Method Overriding.
class Animal { void sound() { System.out.println("Animal"); }}class Dog extends Animal { void sound() { System.out.println("Bark"); }}
Animal a = new Dog();a.sound();
Output:
Bark
Decision happens during runtime.
Overloading vs Overriding#
| Feature | Overloading | Overriding |
|---|---|---|
| Time | Compile Time | Runtime |
| Parameters | Must Change | Same |
| Inheritance Required | ❌ | ✅ |
| Return Type | Can Change | Must Follow Rules |
Enums#
What is an Enum?#
Answer:
Enum is a special type used to represent a fixed set of constants.
enum Status { PENDING, SUCCESS, FAILED}
Why use Enum instead of Strings?#
Without Enum:
String status = "Sucess"; // typo
With Enum:
Status status = Status.SUCCESS;
Compile-time safety.
Can Enums have Constructors?#
Yes.
enum Status { SUCCESS(200); private int code; Status(int code) { this.code = code; }}
Most Asked 5-Minute HR Round OOP Question#
Explain all four pillars of OOP in one answer.#
Encapsulation
Wrapping data and methods together and restricting direct access.
Abstraction
Showing only essential details while hiding implementation.
Inheritance
Acquiring properties and behavior from another class.
Polymorphism
One interface, multiple implementations.
this Keyword#
What is this?#
this is a reference variable that refers to the current object.
Why is it needed?#
When local variables and instance variables have the same name.
class Employee { String name; Employee(String name) { this.name = name; }}
Without this:
name = name;
The compiler assumes both are local variables.
Uses of this#
1. Refer Current Object
this.name
2. Invoke Current Class Method
this.display();
3. Constructor Chaining
class Student { Student() { this(100); } Student(int id) { System.out.println(id); }}
4. Pass Current Object
process(this);
Interview Question#
Can we use this inside a static method?
No.
Reason:
Static methods belong to the class.
this belongs to an object.
static void test() { System.out.println(this); // Error}
super Keyword#
What is super?#
super refers to the immediate parent class object.
Why use super?#
To access:
- Parent variables
- Parent methods
- Parent constructors
Access Parent Variable#
class Animal { String name = "Animal";}class Dog extends Animal { String name = "Dog"; void print() { System.out.println(super.name); }}
Output:
Animal
Call Parent Method#
class Animal { void sound() { System.out.println("Animal Sound"); }}class Dog extends Animal { void sound() { super.sound(); System.out.println("Bark"); }}
Output:
Animal SoundBark
Call Parent Constructor#
class Animal { Animal() { System.out.println("Animal"); }}class Dog extends Animal { Dog() { super(); System.out.println("Dog"); }}
Output:
AnimalDog
Interview Question#
Which executes first?
super()
or
this()
Answer:
Only one can exist as the first statement.
Dog() { super();}
or
Dog() { this(10);}
Never both.
Constructor Chaining#
What is Constructor Chaining?#
Calling one constructor from another constructor.
Purpose:
Avoid duplicate initialization code.
Using this()#
class Student { Student() { this(101); } Student(int id) { System.out.println(id); }}
Output:
101
Using super()#
class Person { Person() { System.out.println("Person"); }}class Student extends Person { Student() { super(); System.out.println("Student"); }}
Output:
PersonStudent
Interview Question#
Can this() and super() appear together?
No.
Both must be first statement.
Compiler error.
Student() { this(1); super(); // Error}
Object Class#
What is Object Class?#
Every class in Java directly or indirectly inherits from:
java.lang.Object
class Employee {}
Actually becomes:
class Employee extends Object {}
Common Methods#
toString()
equals()
hashCode()
getClass()
clone()
toString()#
Purpose#
Returns string representation of an object.
Without overriding:
Employee e = new Employee();System.out.println(e);
Output:
Employee@7a81197d
Override it:
class Employee { String name; Employee(String name) { this.name = name; } public String toString() { return name; }}
Output:
Rakshit
Interview Question#
Why override toString()?
For meaningful logging and debugging.
equals()#
Default Behavior#
Compares references.
String a = new String("Hello");String b = new String("Hello");System.out.println(a == b);
Output:
false
System.out.println(a.equals(b));
Output:
true
Why Override equals()?#
To compare object contents instead of memory addresses.
class Employee { int id; Employee(int id) { this.id = id; } public boolean equals(Object o) { Employee e = (Employee)o; return this.id == e.id; }}
Interview Trap#
Difference between == and equals()
== | equals() |
|---|---|
| Compares reference | Compares content |
| Operator | Method |
| Faster | Customizable |
hashCode()#
What is hashCode?#
Returns integer hash representation of object.
Used by:
- HashMap
- HashSet
- Hashtable
Example
Employee e1 = new Employee(1);Employee e2 = new Employee(1);
If:
e1.equals(e2) == true
Then:
e1.hashCode() == e2.hashCode()
Must also be true.
Golden Interview Rule#
Whenever you override:
equals()
also override:
hashCode()
Bad:
equals() overriddenhashCode() not overridden
Leads to bugs in HashMap and HashSet.
Most Asked Interview Question#
Why must equal objects have same hashCode?
Because HashMap first uses hashCode to locate a bucket.
Then uses equals() to find the exact object.
If hashCode differs:
The object cannot be found.