In Object Oriented Programming, there is a significant concept that can help us to reuse the code in various contexts without the need to rewrite the same code many times. It helps in the code duplication and enhances maintainability of the code. In this blog let us understand about what is Polymorphism? Why do we use Polymorphism and what are the ways through which Polymorphism can be achieved with examples. So without any ado, let's go through the blog.
The word polymorphism is the combination of poly that indicates “many” and morph indicates “forms” which collectively indicates “An object that has many forms”. An Object oriented programming language includes classes and objects using a single interface which would use the concepts of function overloading, function overriding and virtual functions.
Polymorphism refers to the ability to take many forms. It is an important concept in object oriented programming which enables the interface/method to be used with different classes or data types. It enables you to create objects, variables and methods that can have multiple forms. In Polymorphism, the class objects inherited from a common parent class will have the functions with the same name but behave differently.
One of the real time examples is a woman. She acts as a wife to her husband, acts as a mother to her children, acts as an employee to the employer at the same time but in different situations. Here the woman is exhibiting different behaviour in different situations. This is called Polymorphism.
Polymorphism is one of the important concepts in OOPs concepts. It allows us to write adaptable and flexible code that can work with a variety of objects without knowing their specific type at compile time. Following are some of the reasons why Polymorphism is important in object Oriented Programming.
Consider a class hierarchy that has a superclass called fruit, with three subclasses Apple, Orange and grapes. All these three subclasses inherit from fruit. The fruit class had a method known as colour(), that is overridden in the classes Apple, Orange and grapes
IMAGE
Syntax:
Syntax for the above example:
class Fruit
{
public: Fruit(){}
//defining a virtual function called Colour for Fruit class
virtual void Colour(){cout<<"Colour of the Fruit"<<endl;}
};
class Apple: public Fruit
{
public: Apple(){}
//Colour function defined for Apple class
virtual void Colour(){cout<<"Red"<<endl;}
};
class Orange: public Fruit
{
public: Orange(){}
//Colour function defined for Orange class
virtual void Colour(){cout<<"Orange"<<endl;}
};
class Grapes: public Fruit
{
public: Grapes(){}
//Colour function defined for Grapes class
virtual void Colour(){cout<<"Green"<<endl;}
};
int main() {
Fruit *f;
Orange O;
Apple A;
Grapes G;
// store the address of Apple
f = &A;
// call Apple Colour function
f->Colour();
// store the address of Orange
f = &O;
// call Orange Colour function
f->Colour();
// store the address of Grapes
f = &G;
// call Grapes Colour function
f->Colour();
return 0;
}
In the above example, We have used polymorphism to call the same method “Colour()” on different objects and the method resulted in the different output depending on the type of object. This is how Polymorphism works. It enables you to write the code that can work with distinct objects without the need to know their specific type at the compile time.
IMAGE
Compile time polymorphism is also called static binding or early binding. It is a type of Polymorphism that is achieved either by method/function overloading or Operator overloading. The overloaded functions will be invoked by matching the number of arguments and type of arguments. The information is given during the compile time. So at the compile time, appropriate functions will be selected.
Compile time polymorphism is achieved by method/function overloading and operator overloading.
It enables us to define several methods in the same class using the same name providing different parameter lists. When a method is called, then the compiler will determine which method to be invoked depending on the number, type and order of arguments passed. It will allow us to use the same method name for different operations on different data types.
Example:
#include
using namespace std;
class addition
{
public:
int addition(int a, int b)
{
return a + b;
}
float addition(float a, float b, float c)
{
return a + b + c;
}
};
int main(void)
{
addition add;
cout << add.addition(4, 5) << endl;
cout << add.addition(1.2, 4.3, 7.1) << endl;
return 0;
}
Output:
9
12.6
In the above example, the addition class has two addition methods with the same name but different parameter types (integers and float). When a method is called, then the compiler will determine which method to be invoked depending on the number, type and order of arguments passed.
It allows operators like -, +, *, etc., to be overloaded and used with various types of operands. The overloaded operators' behaviour is according to the types of Operands involved.
Example
#include
using namespace std;
class Demo
{
private:
int num;
public:
Demo(): num(6){}
void operator ++() {
num = num+3;
}
void Print() {
cout<<"the result is : "<<num;
}
};
int main()
{
Demo d;
++d; // calling of a function "void operator ++()"
d.Print();
return 0;
}
Output:
the result is : 9
Runtime Polymorphism is also called dynamic binding or late binding. It is achieved by method overriding when the method of the object is invoked at the run time rather than during the compile time. Runtime polymorphism can be achieved by method overriding and virtual functions.
It enables subclasses to offer a different implementation of the method which is defined already in the superclass.When the method is called on an object of the subclass, the method that is overridden in the subclass will be executed rather than the method in the superclass. It allows us to offer a specific implementation of the method in the subclass which is different from the implementation in the superclass.
Example:
#include
using namespace std;
class Animal {
public: void sound()
{
cout<<"making sound...";
}
};
class Cat: public Animal
{
public:
void sound()
{
cout<<"Meow Meow...";
}
};
int main(void) {
Cat c = Cat();
c.sound();
return 0;
}
Output:
Meow Meow...
These are the functions that are declared in the base class using the Keyword “virtual” and are intended to be overridden in the derived classes. The actual functions that must be executed are dynamically determined as per the object type.
Example
#include
using namespace std;
class Draw {
public:
virtual void start() {
cout << "Start to Draw" << endl;
}
};
class Circle : public Draw {
public:
void start() {
cout << "Draw a circle" << endl;
}
};
int main() {
Draw* dPtr;
Circle cObj;
dPtr = &cObj; // Assigning address of Circle object to the base class pointer
dPtr->start(); // Output: Draw a circle
return 0;
}
In the above example, we have written a base class Shape with a virtual function draw(). Here the Circle class inherits from the Shape class and overrides the draw() function with its own implementation. In the main() function, we have declared a pointer dPtr of type Shape* and created a Circle object cObj. Then we have assigned the address of the cObj to the dPtr. This is because of the "is-a" relationship between Circle and Shape.
When we call the draw() function through the pointer dPtr, the overridden version of the draw() function in the Circle class is executed at runtime. This is called runtime polymorphism, as the actual function to be executed is dynamically determined as per the type of Object at runtime.
Using pointers/references to the base class or virtual functions, we could achieve polymorphic behaviour, where different objects of derived classes can be treated uniformly through the base class interface, allowing for code reusability and flexibility.
When working with Polymorphism in OOP, you need to avoid certain things to ensure correct and effective usage. Following are some i the common mistake that are to be avoided:
By keeping in mind all these things you can follow the best practices and use polymorphism effectively in Object oriented programming.
Conclusion:
In this blog, we have learned what is Polymorphism in Object oriented programming, why is polymorphism used, Types of Polymorphism with examples and mistakes to be avoided while implementing polymorphism. We hope you found the information helpful. For more blogs related to Object Oriented Programming, stay tuned to HKR Trainings.
Related Article:
Batch starts on 28th Sep 2023, Weekday batch
Batch starts on 2nd Oct 2023, Weekday batch
Batch starts on 6th Oct 2023, Fast Track batch
.