Object-Oriented Programming (OOP) is a programming paradigm, or a way of thinking about and structuring code, that organizes software design around objects rather than functions and logic.
It aims to model real-world entities and their interactions within a program.
Let us have a look at the main features of OOP.
1. Encapsulation
It refers to the bundling of data (variables) and methods (functions) that operate on the data into a single unit (i.e., a class), and restricting access to some of the objectβs components.
This helps to protect the internal state of the object and prevents external interference and misuse.
π Key Concepts of Encapsulation :
- Private Fields: Instance variables are kept private to restrict direct access;
- Public Getters/Setters: Provide controlled access to fields using public methods;
- Data Hiding: Internal representation is hidden from outside classes.
β Benefits of Encapsulation :
- Security: Sensitive data is hidden from the outside;
- Maintainability: Internal implementation can change without affecting external code;
- Reusability: Class can be reused without exposing internal logic;
- Flexibility: You can control access using logic in setters/getters.
π§ͺ Example of Encapsulation :
public class BankAccount {
// Private fields (data hiding)
private String accountNumber;
private double balance;
// Constructor
public BankAccount(String accountNumber, double initialBalance) {
this.accountNumber = accountNumber;
this.balance = initialBalance;
}
// Public getter for account number
public String getAccountNumber() {
return accountNumber;
}
// Public getter for balance
public double getBalance() {
return balance;
}
// Public method to deposit money (with validation)
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
// Public method to withdraw money (with validation)
public boolean withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
return true;
}
return false;
}
public static void main(String[] args) {
BankAccount account = new BankAccount("12345", 1000.0);
// Cannot directly access balance (it's private)
// account.balance = 5000; // β Compilation error
// Use public methods to interact
account.deposit(500);
account.withdraw(200);
System.out.println("Account Balance: $" + account.getBalance());
}
}
/*
* Output:
* Account Balance: $1300.0
*/
Above code snippet demonstrates encapsulation in Java by using private fields and public methods to control access to the data.
The BankAccount class encapsulates the account number and balance, providing methods to deposit and withdraw money while ensuring that the balance cannot be set directly from outside the class.
2. Inheritance
It allows a class (child/subclass) to inherit properties and behavior (fields and methods) from another class (parent/superclass).
This promotes code reusability, extensibility, and establishes a natural hierarchy between classes.
π Key Concepts of Inheritance :
- Superclass / Base Class / Parent Class: The class being inherited from;
- Subclass / Derived Class / Child Class: The class that inherits from the superclass;
- A subclass “is a” type of its superclass;
- The subclass can override or extend the behavior of the parent.
β Benefits of Inheritance :
- Code reuse: Common logic in the base class doesnβt need to be rewritten;
- Polymorphism: Objects of subclasses can be treated as instances of the superclass;
- Organization: Models real-world relationships (e.g., a Dog “is an” Animal).
π§ͺ Example of Inheritance :
public class InheritanceExample {
// Superclass
private static class Animal {
public void eat() {
System.out.println("This animal eats food.");
}
public void sleep() {
System.out.println("This animal sleeps.");
}
}
// Subclass
private static class Dog extends Animal {
public void bark() {
System.out.println("The dog barks.");
}
// Overriding the eat method
@Override
public void eat() {
System.out.println("The dog eats bones.");
}
}
public static void main(String[] args) {
Dog myDog = new Dog();
// Inherited methods
myDog.sleep(); // From Animal
myDog.eat(); // Overridden in Dog
// Dog's own method
myDog.bark();
}
}
/*
* Output :
*
* This animal sleeps.
* The dog eats bones.
* The dog barks.
*/
3. Polymorphism
Polymorphism means “many forms”.
It allows objects of different classes to be treated as objects of a common superclass, typically through method overriding/overloading or interfaces.
It lets developers write code that works on the parent type, but behaves differently depending on the actual child type at runtime.
π Types of Polymorphism in Java :
- Compile-Time Polymorphism (Method Overloading)
- Runtime Polymorphism (Method Overriding)
π‘ Why Use Polymorphism ?
- Cleaner code: Treat different objects the same way;
- Extensibility: Easy to add new behaviors via subclassing;
- Decoupling: Promotes coding to interfaces/superclasses instead of specific classes.
β Example of Runtime Polymorphism (Method Overriding)
public class PolymorphismExample {
// Superclass
private static class Animal {
public void makeSound() {
System.out.println("Some generic animal sound");
}
}
// Subclass 1
private static class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Woof!");
}
}
// Subclass 2
private static class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Meow!");
}
}
public static void main(String[] args) {
Animal myAnimal;
myAnimal = new Dog();
myAnimal.makeSound(); // Output: Woof!
myAnimal = new Cat();
myAnimal.makeSound(); // Output: Meow!
}
}
/*
* Output :
*
* Woof!
* Meow!
*/
In above code snippet, even though the variable is of type Animal, the actual method called depends on the object type (Dog or Cat), this is runtime polymorphism.
β Example of Compile-time Polymorphism (Method Overloading)
public class PolymorphiseExample2 {
private static class Calculator {
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) {
return a + b;
}
}
public static void main(String[] args) {
Calculator calc = new Calculator();
// Using the int version
int intResult = calc.add(5, 10);
System.out.println("Integer addition: " + intResult); // Output: Integer addition: 15
// Using the double version
double doubleResult = calc.add(5.5, 10.2);
System.out.println("Double addition: " + doubleResult); // Output: Double addition: 15.7
}
}
/*
* Output :
*
* Integer addition: 15
* Double addition: 15.7
*/
In above code snippet, the method add is overloaded with different parameter types/counts.
The correct method is chosen at compile-time.
4. Abstraction
It consists of hiding internal implementation details and exposing only the relevant features to the user.
Think of abstraction as focusing on what an object does, rather than how it does it.
β Real-World Analogy
Consider a TV remote:
- You press a button to increase volume or change the channel;
- You don’t care how the remote sends infrared signals to the TV;
- The complex logic is abstracted away from the user.
π‘ Benefits of Abstraction
- β Reduces code complexity;
- β Increases security by hiding implementation details;
- β Improves modularity and flexibility;
- β Promotes coding to interfaces, not implementations.
π§ Abstraction in Java
Java supports abstraction in two main ways :
- Abstract Classes
- Interfaces
β¨ 1. Abstract Class Example
public class AbstractionExample {
private static abstract class Animal {
// Abstract method - no body
public abstract void makeSound();
// Concrete method
public void sleep() {
System.out.println("Sleeping...");
}
}
private static class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Woof!");
}
}
public static void main(String[] args) {
// Create a Dog object
Animal myDog = new Dog();
// Call the abstract method
myDog.makeSound(); // Output: Woof!
// Call the concrete method
myDog.sleep(); // Output: Sleeping...
}
}
/*
* Output :
*
* Woof!
* Sleeping...
*/
In above code snippet, Animal hides the implementation of makeSound β forcing subclasses to provide their version, Dog implements the behavior.
β¨ 2. Interface Example
public class AbstractionExample2 {
private static interface Vehicle {
void start();
void stop();
}
private static class Car implements Vehicle {
@Override
public void start() {
System.out.println("Car started");
}
@Override
public void stop() {
System.out.println("Car stopped");
}
}
public static void main(String[] args) {
Vehicle myCar = new Car();
myCar.start(); // Car started
myCar.stop(); // Car stopped
}
}
/*
* Output :
*
* Car started
* Car stopped
*/
In above code snippet, The Vehicle interface defines what should be done (start(), stop()), but not how, Car provides the implementation.
Summary of OOP Features
FEATURE | DEFINITION | GOAL | MECHANISM IN JAVA |
---|---|---|---|
Encapsulation | Bundling data (fields) and methods (functions) that operate on the data into a single unit (class), and restricting direct access to some of the object’s components | Hide internal state and require all interaction to be performed through an object’s methods | Access modifiers (public, protected, private), getters/setters |
Inheritance | A mechanism where one class (child/subclass) can inherit fields and methods from another class (parent/superclass) | Promote code reuse and create a hierarchical relationship between classes | extends or implements |
Polymorphism | The ability of different classes to be treated as instances of the same class through a common interface or superclass | Write more generic and reusable code that works on the base type but can execute behavior from derived types | Method overriding/overloading interfaces |
Abstraction | Hiding the complex implementation details and showing only the essential features of the object | Reduce complexity and increase efficiency by focusing on relevant details | Abstract classes/interfaces |