Pagine

6 febbraio 2008

Lesson 5: Polymorphism

In the previous lesson (Class Inheritance) we learned how a class can derive from another one and inherit the properties of the mother.

Along with inheritance, Object Orientation is based on the so called polymorphism, let's see what it means.


Polymorphism: evolving beside inheriting


To understand the meaning of polymorphism, you have to have clear in mind the following statement:

A pointer to a derived class is type-compatible with a pointer to its mother class.

What does this mean? Look at the following example (I'm against war, but the army structure nicely fit this example).

class Soldier {

 public:
   virtual void defend() { return ; // nothing to do }
   virtual void attack()  { return ; // nothing to do }
};

class Artilleryman : public Soldier {

 public:
   void defend() { 
      // define here the specific way
      // an artilleryman defends
      // for example:
      avoidAttack();
   }
   void attack() { 
      // define here the specific way
      // an artilleryman attacks
      // for example:
      if ( !isGunLoaded() ) loadGun();
      aimClosestEnemy();
      fire();
   }
}

class Bowman : public Soldier {

 public:
   void defend() { 
      // define here the specific way
      // a bowman defends
      // it may be the same as others
      avoidAttack();
   }

   void attack()  { 
      // define here the specific way
      // a bowman defends
      // for example:
      if ( doYouHaveArrows() ) {
         takeOneArrow();
         aimClosestEnemy();
         loadTheBow();
         fire();
      } else {
         runAway();
      }
   }
};

int main(int, char**) {

   // declare three soldiers, one per type
   Soldier       mySimpleSoldier;
   Artilleryman  myArtilleryMan;
   Bowman        myBowman;

   // the following line is easy, because is the standard
   // way a pointer is used
   Soldier * mySoldier1 = &mySimpleSoldier;

   // But remember the type-compatibility of derived class
   Soldier * mySoldier2 = &myArtilleryMan;
   Soldier * mySoldier3 = &myBowman;

   // let them attack

   mySoldier1->attack();
   /* nothing should happen because
      we didn't specify the way a "simple"
      soldier attacks
   */

   mySoldier2->attack();
   /* now we should see a gun bullet */

   mySoldier3->attack();
   /* and now an arrow */

   return 0;
}


The member functions attack and defend are declared within the base and all the derived classes. In the Soldier base class the two methods are declared virtual. This means that the derived classes can redefine and re-implement the methods. If you forgot the virtual qualifier the compiler will complain about a re-definition of the method. Don't mistake virtual for not real: even if a method is declared virtual it can be implemented (as in the actual case of the soldier).
Now you should have clear what polymorphism means: the capability of a derived class to implement in a specific way an inherited method. A class which defines or inherits virtual member functions is called polymorphic.

An abstract soldier

The word abstract is quite common in Object Orientation especially in the sentence abstract base class (ABC). In our army example, the good candidate to be an ABC is the soldier class. We need to modify it as follows:

// definition of the soldier abstract base class
class Soldier {
 public:
   virtual void defend() = 0;
   virtual void attack() = 0;
};


We have completely removed the "empty" implementation of the two member functions and we appended a "= 0". With these modifications, the attack and defend methods are called pure virtual functions. Another definition you have to keep in mind is that all classes having at least one pure virtual method are called abstract classes.

Because of the lack of implementation of pure virtual methods, we cannot create instances (objects) of abstract classes. It is to say that the following line of code is producing a compilation error:

Soldier mySimpleSoldier; // fail to compile!

but we are allowed to create pointers to the abstract class and due to the type-compatibility the following code is perfectly valid:

int main(int, char**) {

   Soldier * anySoldier;

   // choose the soldier you want
   if ( doYouWantABowman() ) anySoldier = new Bowman;
   else anySoldier = new Artilleryman;

   // now attack
   anySoldier->attack();


   return 0;
}


As you see in the previous code, having an abstract base class defining the interface to the soldier, we can actually use just one type of pointer (Soldier*) to handle all the possible derived classes. It looks great, doesn't it? Let me say it again using other words carefully looking at the statement:

Soldier * anySoldier = new Artilleryman;


On the left hand side of the equality we have the declaration of anySoldier as a pointer to a Soldier, while on the other side we are dynamically allocating a pointer to an object of the derived class directly and when we call the attack method the Artilleryman implementation is used.

A real life example is the TVirtualFitter class in ROOT.

At this point if you are not saying "Cool... that's really great!", then object oriented programming is not for you. Otherwise, don't go too far away because in the next lesson we will talk about templates!

Ps: If you like this series of lesson, don't forget to share it!

Chiunque può lasciare commenti su questo blog, ammesso che vengano rispettate due regole fondamentali: la buona educazione e il rispetto per gli altri.

Per commentare potete utilizzare diversi modi di autenticazione, da Google a Facebook e Twitter se non volete farvi un account su Disqus che resta sempre la nostra scelta consigliata.

Potete utilizzare tag HTML <b>, <i> e <a> per mettere in grassetto, in corsivo il testo ed inserire link ipertestuali come spiegato in questo tutorial. Per aggiungere un'immagine potete trascinarla dal vostro pc sopra lo spazio commenti.

A questo indirizzo trovate indicazioni su come ricevere notifiche via email sui nuovi commenti pubblicati.

1 commento:

Chiunque può lasciare commenti su questo blog, ammesso che vengano rispettate due regole fondamentali: la buona educazione e il rispetto per gli altri.

Per commentare potete utilizzare diversi modi di autenticazione, da Google a Facebook e Twitter se non volete farvi un account su Disqus che resta sempre la nostra scelta consigliata.

Potete utilizzare tag HTML <b>, <i> e <a> per mettere in grassetto, in corsivo il testo ed inserire link ipertestuali come spiegato in questo tutorial. Per aggiungere un'immagine potete trascinarla dal vostro pc sopra lo spazio commenti.

A questo indirizzo trovate indicazioni su come ricevere notifiche via email sui nuovi commenti pubblicati.