Page 1 of 1

Polymorphism A core concept of OOP Rate Topic: ***** 1 Votes

#1 sparkart  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 113
  • View blog
  • Posts: 691
  • Joined: 16-February 09

Posted 10 November 2010 - 01:22 AM

*
POPULAR

Polymorphism


This tutorial assumes prior knowledge of:
- Inheritance
- Difference between pass-by-reference and pass-by-value
- Pointer/Reference


Note to seasoned programmers: This tutorial tries to cover the subject without introducing anything else as much as possible.



Polymorphism basically comes from the idea of being able to manage data of different types through a common interface. If polymorphism is new to you, this probably sounds strange, so let me give you an example.

In the world, all living things do something in common. All living beings "live" or "exist". Humans are living things and they "live". Cats are living things and they "live". Plants are living things and they "live". They are all different, but behave commonly (to an extent).
class Living
{
public:
  void Live() { std::cout << "Living creature living.\n"; }
};

class Human: public Living
{
public:
  void Live() { std::cout << "Human living.\n"; }
};

class Cat: public Living
{
public:
  void Live() { std::cout << "Cat living.\n"; }
};

class Plant: public Living
{
public:
  void Live(){ std::cout << "Plant living.\n"; }
};



Remember the rules about inheritance. When a class is derived from a base class, the derived class will inherit everything that the base class contains. The derived class has all the properties of a base class plus extra. Also remember that if a method from the base class is redefined in the derived class the derived method replaces the base method.

In our computer simulation, we could maintain our objects like so:
Human listHuman[LIMIT];
Cat listCat[LIMIT];
Plant listPlant[LIMIT];

for ( int i = 0; i < LIMIT; ++i )
{
  listHuman[i].Live();
  listCat[i].Live();
  listPlant[i].Live();
}



If you take some time to digest this, you will find that we have different data types but they behave similarly. They all Live(), the difference is that they Live() differently. Since they behave similarly to this extent, it would be in our best interest to be able to make them Live() through a common interface. Let's look at an example.

In a class, attendance is taken using one list of students. There is no single list for boys and no single list for girls. The reason this works is because boys are students and girls are students. So it makes sense to have one list of students, which contains boys and girls.

For our case, it makes sense to make one list of Living objects.
Living list[LIMIT];

for ( int i = 0; i < LIMIT; ++i )
  list[i].Live();



Now, we are managing three different objects using one interface. We are only using one list and one method, however, we have a problem with the code. list only holds Living objects, yet we are able to store object types of Human, Cat, and Plant. The reason that this is possible is because we know that derived objects are the same as base objects plus extra. If we have a derived object and try to copy it to a base type we just remove the extra and the derived looks exactly like the base. This is called "object slicing". To store a derived type object to a base type variable the derived type needs to be stripped so that it is looks like a base type, which is what the variable stores.
Base storage;
Derived object;

// Pass-by-value a.k.a. copying.
storage = object;


To assign 'object' to 'storage' we make a copy of 'object' as a 'storage' type. This copy is performed by simply stripping the extra properties that come from the 'object' type. Object slicing is generally undesired and it is usually done by accident. A quick panacea to "object slicing" is passing-by-reference.

Living* list[LIMIT];

for ( int i = 0; i < LIMIT; ++i )
  list[i]->Live();


By using references, we avoid object slicing. However, we have another problem. Since the pointer type is Living, the invoked method is Living::Live();. If our pointer type was Human, the method called would be Human::Live();, except we would be deviating from our goal of a single common interface.

To solve this problem, we use the virtual keyword in our method signature: virtual void Live();. When a method uses the virtual keyword, it means that the method to call should always be the method from the derived class (as long as one exists).
class Base
{
public:
  virtual void Method();
};

class Derived: public Base
{
public:
  void Method();
};

Base* b;
Derived d;

// The pointer is of type Base but it points to object Derived.
b = &d;

b->Method();


When we get to this line b->Method(); we wonder, should I call Base::Method() or Derived::Method()? The pointer is a Base, but the object is Derived. Well, Base::Method() was declared with the virtual keyword, so the method to invoke should be from Derived.

Now we can do something like the following code:
Living* list[LIMIT];
// list contains Human, Cat, and Plant objects.
for ( int i = 0; i < LIMIT; ++i )
// Invoked methods are Human::Live(), Cat::Live(), and Plant::Live()
  list[i]->Live();



Having a common interface to manage objects of different type (with similarities to an extent) helps us out quite a bit. Hopefully this tutorial helped clear things up about Polymorphism. If the topic is still a little confusing, hopefully this tutorial has made it less confusing.

Is This A Good Question/Topic? 5
  • +

Replies To: Polymorphism

#2 Anarion  Icon User is online

  • The Persian Coder
  • member icon

Reputation: 311
  • View blog
  • Posts: 1,515
  • Joined: 16-May 09

Posted 10 November 2010 - 04:38 AM

Nice tutorial; although you could discuss how late binding is achieved via virtual calls, as well :)
Was This Post Helpful? 0
  • +
  • -

#3 Aphex19  Icon User is offline

  • Born again Pastafarian.
  • member icon

Reputation: 615
  • View blog
  • Posts: 1,873
  • Joined: 02-August 09

Posted 28 March 2011 - 02:28 AM

Thanks for the clear and concise explanation, it finally clicked with me.

This post has been edited by Aphex19: 28 March 2011 - 02:29 AM

Was This Post Helpful? 0
  • +
  • -

#4 sparkart  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 113
  • View blog
  • Posts: 691
  • Joined: 16-February 09

Posted 04 April 2011 - 04:16 PM

View PostAphex19, on 28 March 2011 - 03:28 AM, said:

Thanks for the clear and concise explanation, it finally clicked with me.

I am glad that this tutorial was helpful for you. My only request would be that you spread it to others (that need help understanding the concept) like wildfire. :)
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1