What is Programming Paradigm?
A programming paradigm is a fundamental style or approach to programming that guides how solutions to problems are structured and expressed in a programming language. Each paradigm provides a set of rules, principles, and techniques for designing, writing, and organizing code.
A programming paradigm is like a style or a set of rules that programmers use to write code.
In simple terms, it's a way of thinking about writing software.
Just like there are different styles of cooking—such as Italian, Indian, or Chinese cuisine—there are different programming paradigms, which are styles or approaches to writing code.
Each cuisine has its own techniques, tools, and philosophy, and so does each programming paradigm.
- Procedural Programming is like following a recipe step by step – chop, cook, stir, serve. You focus on how things are done.
- Example C.
- Object-Oriented Programming is like a professional kitchen where each chef (object) is in charge of specific tasks (methods) and ingredients (data). They communicate and collaborate to prepare a dish.
- Example: C++, Java.
Main Types of Programming Paradigms
Paradigm | Description |
---|---|
Procedural | Focuses on a sequence of instructions (procedures or functions). Example: C, Pascal |
Object-Oriented (OOP) | Organizes code into objects that contain both data and methods. Example: C++, Java |
Functional | Treats computation as evaluation of mathematical functions, avoids changing state. Example: Haskell, Lisp |
Logic-based | Uses rules and facts to derive conclusions. Example: Prolog |
Declarative | Focuses on what to do, not how to do it. Example: SQL, HTML |
Difference Between Procedural Programming and Object Oriented Programming
There are two major programming paradigms: Procedural Programming and Object-Oriented Programming (OOP). They differ in several fundamental ways:
1 Approach:
- Procedural Programming: Follows a step-by-step, linear approach where tasks are carried out through procedures or functions in a sequential manner.
- OOP: Models real-world entities as objects that encapsulate both data (attributes) and behavior (methods). Control flow is governed by object interactions rather than a strict sequence.
2 Data Handling:
- Procedural Programming: Data is typically global or passed between functions, making it prone to unintended modifications and harder to manage in large codebases.
- OOP: Uses encapsulation to restrict data access via public methods. This enhances data security and integrity by exposing only necessary parts of an object.
3 Code Reusability:
- Procedural Programming: Functions allow limited reuse, but lacks advanced mechanisms like inheritance or polymorphism.
- OOP: Promotes high reusability through inheritance, polymorphism, and abstraction, enabling flexible and extensible code.
4 Scalability:
- Procedural Programming: Less scalable for large systems; changes often require modifications in multiple places, increasing the risk of bugs.
- OOP: High scalable; new features can be added by extending classes or creating new ones without affecting unrelated code.
5 Modularity:
- Procedural Programming: Divides code into functions, but data and logic are less encapsulated, making maintenance harder in complex systems.
- OOP: Organizes code into classes and objects, ensuring better modularity and separation of concerns.
6 Real-World Modeling:
- Procedural Programming: More abstract and focused on actions, making it harder to map directly to real-world systems.
- OOP: Naturally aligns with real-world thinking by representing entities as objects, improving intuitiveness and system design.
Use-Cases of Object Oriented Programming
There are four major factors that make OOP significantly used in the real world. These are as follows:
- Modularity: The process of breaking down a complex problem into smaller, manageable, and reusable components (such as classes), enhancing code organization and maintainability.
Example: a banking application with separate classes for Account, Customer, Transaction, etc. - Code Reusability: Refers to the ability to extend and reuse existing functionality, reducing the need to duplicate code and promoting maintainability.
Example: Vehicle class extended by Car and Bike. - Scalability: Refers to the ability to effortlessly add new features or functionality without modifying existing code, ensuring the system can grow and adapt without disruption.
- Security: Using OOP, users can protect sensitive data by encapsulating it within objects and exposing only the necessary functionality through controlled access methods, ensuring data integrity and security.
Example: private balance in a Bank Account class.
Object-oriented programming
Object-oriented programming (OOP) is a programming paradigm based on the concept of "objects," which can contain data (attributes
) and code (methods
) to manipulate that data. In C++, OOP is a core feature, allowing developers to model real-world entities and their interactions in a structured and modular way.
It majorly consists of two things:
- Class: A class is blueprint or template that defines the properties (attributes) and behaviors (methods) common to all object of its type.
- Object: An object is an instance of a class, representing a specific entity with its own unique state (attributes values) and behavior.
Real-life Analogy of Object Oriented Programming
Let us consider the codebase of a Bank.
- Classes: Represent different entities in the bank, such as Account, Customer, and Transaction.
- Objects: Specific instances of those classes, like Ajay's Account, or John’s Transaction.
- Attributes: Information associated with each entity, like a customer's name, balance, or account number.
- Methods: Actions the bank entities can perform, such as deposit(), withdraw(), and transfer().
1️⃣ Encapsulation:
Encapsulation is the bundling of data (attributes or properties
) and methods (functions or procedures
) that operate on that data into a single unit, called a class
. This principle hides the internal workings (data and implementation details) of an object from the outside world, exposing only what is necessary through a public interface.
- Example: Consider a Car class that encapsulates attributes like make, model, and year, along with methods like start(), accelerate(), and brake(). The internal details of how these methods work are hidden from the user of the Car class.
Class:
A blueprint for creating objects. It defines what properties (data members) and behaviors (member functions) the objects created from it will have.
Example:
class Car {
private:
int speed;
public:
void setSpeed(int s) {
speed = s;
}
int getSpeed() {
return speed;
}
};
Access Specifiers:
private
: The data or methods are only accessible within the class itself.public
: The data or methods can be accessed from outside the class.protected
: The data or methods can be accessed by derived classes (useful for inheritance).
Encapsulation allows you to control access to the internal state of an object and ensures that data integrity is maintained by only allowing controlled interaction with the object.
2️⃣ Abstraction:
Abstraction refers to the process of simplifying complex systems by focusing on essential properties while hiding unnecessary details. In OOP, abstraction is achieved by defining a clear and concise public interface for interacting with objects, while hiding the implementation details. This allows a programmer to work with high-level concepts without needing to understand the low-level details.
- Example: When using a List data structure in a programming language, you don't need to know how the list is implemented internally (e.g., as an array or linked list). You only need to know how to use the public methods provided by the List interface, such as add(), remove(), and get().
In C++, abstraction is achieved through:
- Classes: They abstract real-world entities by hiding unnecessary details (using access specifiers like
private
andprotected
) and providing a clean interface (public
functions). - Abstract Classes: These are classes with at least one pure virtual function. They are used to provide an abstract interface for derived classes to implement.
Example:
class AbstractDevice {
public:
virtual void powerOn() = 0; // Pure virtual function (abstract method)
};
class Phone : public AbstractDevice {
public:
void powerOn() override {
cout << "Phone is powering on" << endl;
}
};
3️⃣ Inheritance:
Inheritance is a mechanism that allows a class (derived or child class
) to inherit attributes and behaviors from another class (base or parent class
). The derived class can extend or override the functionality of the base class. This promotes code reuse and establishes an "is-a" relationship between classes.
- Base | Parent Class: The class from which properties and methods are inherited.
- Derived | Child Class: The class that inherits from the base class.
Example: Consider a Vehicle class with attributes and methods common to all vehicles. We can then create more specific classes like Car, Truck, and Motorcycle that inherit from the Vehicle class. These subclasses inherit the common attributes and methods of Vehicle and can add their own unique attributes and methods.
Example:
class Vehicle {
public:
int wheels;
void move() {
cout << "Vehicle is moving" << endl;
}
};
class Car : public Vehicle {
public:
string model;
};
Here, Car
is a derived class, and it inherits the wheels
member and the move()
method from the Vehicle
base class. It can also have its own unique members.
Types of Inheritance:
- Single Inheritance: One derived class inherits from one base class.
- Multiple Inheritance: One derived class inherits from multiple base classes.
- Multilevel Inheritance: A derived class is inherited by another class, forming a hierarchy.
- Hierarchical Inheritance: Multiple derived classes inherit from a single base class.
- Hybrid Inheritance: A combination of two or more types of inheritance.
4️⃣ Polymorphism:
Polymorphism means "many forms," and in C++ it refers to the ability of functions and objects to operate in different ways depending on the context. It allows the same interface to be used for different data types and behaviors.
OR
Polymorphism allows objects of different classes to be treated as objects of a common base class type. It enables code to operate on objects of different types in a uniform manner. Polymorphism can be achieved through method overriding and method overloading.
- Example: Suppose we have a Shape base class with a draw() method. We can create subclasses like Circle, Rectangle, and Triangle that override the draw() method with their own implementations. When we call the draw() method on a Shape object, the appropriate implementation based on the actual type of the object will be invoked. Additionally, method overloading allows us to define multiple methods with the same name but different parameters, further enhancing polymorphic behavior.
There are two types of polymorphism in C++:
🅰️ Compile-Time Polymorphism (Static Polymorphism)
This is achieved through function overloading and operator overloading, where the function or operator behaves differently based on its parameters at compile-time.
Function Overloading: Defining multiple functions with the same name but different signatures (number or types of parameters).
class Printer { public: void print(int i) { cout << "Printing int: " << i << endl; } void print(double d) { cout << "Printing double: " << d << endl; } };
Operator Overloading: Customizing the behavior of operators for user-defined types.
class Complex { public: int real, imag; Complex operator + (const Complex& obj) { Complex temp; temp.real = real + obj.real; temp.imag = imag + obj.imag; return temp; } };
🅱️ Run-Time Polymorphism (Dynamic Polymorphism)
This is achieved through function overriding and virtual functions, where the decision of which function to invoke is made at runtime based on the object type.
Function Overriding: A derived class provides its own implementation for a method that is already defined in the base class.
Example:
class Animal { public: virtual void sound() { cout << "Animal makes a sound" << endl; } }; class Dog : public Animal { public: void sound() override { cout << "Dog barks" << endl; } };
- Virtual Functions: When a base class declares a function as
virtual
, it allows the derived class to override it. The correct method is called at runtime depending on the type of object. Pure Virtual Functions and Abstract Classes: A pure virtual function is declared by assigning
0
to a virtual function, making the class abstract and uninstantiable, forcing derived classes to provide an implementation.class Shape { public: virtual void draw() = 0; // pure virtual function }; class Circle : public Shape { public: void draw() override { cout << "Drawing Circle" << endl; } };