I have Silly Question on OOPs concept, what is reason we go for polymorphism??
Simple code in C++:
class Shape{
public:
virtual void draw(){ cout<<"Shape"<<endl;};
};
class Traingle: public Shape
{
public: void draw(){cout<<"Triangle"<<endl;}
};
class Rectangle: public Shape
{
public: void draw (){cout<<"Rectangle"<<endl;}
};
int main(){
Shape *ptr= new Traingle();
ptr->draw();
delete ptr;
return 7;
}
Here ptr->draw() function will call the Triangle draw, if pointed to Rectangle then Rectangle draw, which is late binding.
What is necessity of creating Base class pointer and point it to different classes? We can create separate class object without any virtual function and call whicever needed. like
int main(){
Traingle tObj;
tObj->draw();
Rectangle rObj;
rObj->draw();
}
which basically does the same thing;
Why polymorphism basically? why virtual?
What is the need of it or what difference does it make using this property? And real case example would help!!
Polymorphism is one of the core concepts in OOP languages and describes the concept wherein you can use different classes with the same interface. Each of these classes can provide its own implementation of the interface.
Polymorphism in C++ allows us to reuse code by creating one function that's usable for multiple uses. We can also make operators polymorphic and use them to add not only numbers but also combine strings. This saves time and allows for a more streamlined program.
Polymorphism requires inheritance and an overridden function. Shape is the superclass or parent class; Circle , Rectangle , and Triangle are all subclasses or children of Shape . The draw functions in the subclasses override the draw function in the Shape class.
Polymorphism allows reuse of code by allowing objects of related types to be treated the same.
Consider that you might need dozens of subclasses that behave differently:
struct Shape1: public Shape { /* .. */ }; // triangle
struct Shape2: public Shape { /* .. */ }; // rectangle
// ...
struct ShapeN: public Shape { /* .. */ }; // projection of rhombic triacontahedron
Consider that you might need to process objects pointed by an array of Shape
pointers.
With polymorphism, you need a single vector, and a single loop with virtual function calls:
std::vector<Shape*> v = get_shape_vector();
for(Shape* s : v)
s->draw();
Without polymorphism, you would have manage a separate array for each type and process them separately:
std::vector<Shape1> v1 = get_shape1_vector();
std::vector<Shape2> v2 = get_shape2_vector();
// ...
std::vector<ShapeN> vN = get_shapeN_vector();
for(Shape1& s : v1)
s.draw();
for(Shape2& s : v2)
s.draw();
// ...
for(ShapeN& s : vN)
s.draw();
The 3 lines of code using polymorphism are way easier to maintain than the 3*N lines of code not using polymorphism.
Consider that you might need to modify the process. Perhaps you want to add a function call before drawing. This is simple when you have polymorphism on your side:
void pre_draw(Shape*);
for(Shape* s : v) {
pre_draw(s);
s->draw();
}
Without polymorphism, you need to define dozens of functions and modify each of the dozen loops:
void pre_draw1(Shape1&);
void pre_draw2(Shape2&);
// ...
void pre_drawN(ShapeN&);
for(Shape1& s : v1) {
pre_draw1(s);
s.draw();
}
for(Shape2& s : v1) {
pre_draw2(s);
s.draw();
}
// ...
for(ShapeN& s : v1) {
pre_drawN(s);
s.draw();
}
Consider that you may add shapes later. With polymorphism, you simply need to define the new type, and the virtual function. You can simply add pointers to it into the array and they will be processed just like objects of every other compatible type.
struct ShapeN1: public Shape { /* .. */ }; // yet another shape
Without polymorhpism, besides defining the new type, you would have to create a new array for it. And you would need to create a new pre_draw
function. And you would need to add a new loop to process them.
void pre_drawN1(ShapeN1&);
// ...
std::vector<ShapeN1> vN1 = get_shapeN1_vector();
// ...
for(ShapeN1& s : vN1) {
pre_drawN1(s);
s.draw();
}
In fact, you would need to go through your entire code base for places where each of the shape type is processed and add the code for the new type there.
Now, N might be small or great. The greater N is, the more repetition polymorphism avoids. But, no matter how few subclasses you have, not having to look through your entire code base when you add a new one is a great boon.
Imagine a base class Shape
. It exposes a GetArea
method. Imagine a Square
class and a Rectangle
class, and a Circle
class. Instead of creating separate GetSquareArea
, GetRectangleArea
and GetCircleArea
methods, you get to implement just one method in each of the derived classes. You don't have to know which exact subclass of Shape
you use, you just call GetArea
and you get your result, independent of which concrete type is it.
Have a look at this code:
#include <iostream>
using namespace std;
class Shape
{
public:
virtual float GetArea() = 0;
};
class Rectangle : public Shape
{
public:
Rectangle(float a) { this->a = a; }
float GetArea() { return a * a; }
private:
float a;
};
class Circle : public Shape
{
public:
Circle(float r) { this->r = r; }
float GetArea() { return 3.14f * r * r; }
private:
float r;
};
int main()
{
Shape *a = new Circle(1.0f);
Shape *b = new Rectangle(1.0f);
cout << a->GetArea() << endl;
cout << b->GetArea() << endl;
}
An important thing to notice here is - you don't have to know the exact type of the class you're using, just the base type, and you will get the right result. This is very useful in more complex systems as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With