What is Programming Paradigm?
A programming paradigm is a fundamental style or approach to programming that dictates 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.
Just like there are different styles of cooking (like Italian, Indian, or Chinese cuisine), there are different programming paradigms.
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.
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; } };