چند ریختی (polymorphism)

چند ریختی به کلاسهایی که در یک سلسله مراتب وراثتی مشابه هستند اجازه تغییر شکل و سازگاری مناسب می دهد و همچنین به برنامه نویس این امکان را می دهد که به جای ایجاد برنامه های خاص، برنامه های کلی و عمومی تری ایجاد کند. به عنوان مثال در دنیای واقعی همه حیوانات غذا می خورند، اما روش های غذا خوردن آنها متفاوت است. در یک برنامه برای مثال، یک کلاس به نام Animal ایجاد می کنید. بعد از ایجاد این کلاس می توانید آن را چند ریخت (تبدیل) به کلاس Bird کنید و متد ()Fly را فراخوانی کنید. به مثالی درباره چند ریختی توجه کنید :

   1: #include <iostream>
   2: using namespace std;
   3: 
   4: class Animal
   5: {
   6:     public:
   7:         virtual void Eat()
   8:         {
   9:             cout << "The animal ate!" << endl;
  10:         }
  11: };
  12: 
  13: class Dog : public Animal
  14: {
  15:     public:
  16:         void Eat()
  17:         {
  18:             cout << "The dog ate!" << endl;
  19:         }
  20: };
  21: 
  22: class Bird : public Animal
  23: {
  24:     public:
  25:         void Eat()
  26:         {
  27:             cout << "The bird ate!" << endl;
  28:         }
  29: };
  30: 
  31: class Fish : public Animal
  32: {
  33:     public:
  34:         void Eat()
  35:         {
  36:             cout << "The fish ate!" << endl;
  37:         }
  38: };
  39: 
  40: int main()
  41: {
  42:     Dog    myDog ;
  43:     Bird   myBird;
  44:     Fish   myFish;
  45:     Animal myAnimal;
  46: 
  47:     myAnimal.Eat();
  48: 
  49:     Animal *animal1 = &myDog;  
  50:     animal1->Eat();           
  51:     Animal *animal2 = &myBird;
  52:     animal2->Eat();           
  53:     Animal *animal3 = &myFish;
  54:     animal3->Eat();           
  55: }
The animal ate!
The dog ate!
The bird ate!
The fish ate!

همانطور که مشاهده می کنید 4 کلاس مختلف تعریف کرده ایم. Animal کلاس پایه است و سه کلاس دیگر از آن مشتق می شوند. هر کلاس متد ()Eat مربوط به خود را دارد. نمونه ای از هر کلاس ایجاد کرده ایم (45-42). سپس متد ()Eat را به وسیله نمونه ایجاد شده از کلاس Animal فراخوانی می کنیم(خط 47).
در مرحله بعد چندریختی روی می دهد. همانطور که در مثال بالا مشاهده می کنید شی Dog را با استفاده از عمل UpCast برابر نمونه ایجاد شده از کلاس Animal قرار می دهیم (خط 49) و متد ()Eat را بار دیگر فراخوانی می کنیم(خط 50). حال با وجود اینکه ما از نمونه کلاس Animal استفاده کرده ایم ولی متد ()Eat کلاس Dog فراخوانی می شود. این به دلیل تاثیر چند ریختی است. سپس دو شی دیگر (Bird و Fish) را برابر نمونه ایجاد شده از کلاس Animal قرار می دهیم(خطوط 51 و 53) و متد ()Eat مربوط به هر یک را فراخوانی می کنیم(خطوط 52 و 54).اجازه دهید که برنامه بالا را اصلاح کنیم تا مفهوم چند ریختی را بهتر متوجه شوید :

   1: #include <iostream>
   2: using namespace std;
   3: 
   4: class Animal
   5: {
   6:     public:
   7:         virtual void Eat()
   8:         {
   9:             cout << "The animal ate!" << endl;
  10:         }
  11: };
  12: 
  13: class Dog : public Animal
  14: {
  15:     public:
  16:         void Eat()
  17:         {
  18:             cout << "The dog ate!" << endl;
  19:         }
  20:         void Run()
  21:         {
  22:             cout << "The dog ran!" << endl;
  23:         }
  24: };
  25: 
  26: class Bird : public Animal
  27: {
  28:     public:
  29:         void Eat()
  30:         {
  31:             cout << "The bird ate!" << endl;
  32:         }
  33:         void Fly()
  34:         {
  35:             cout << "The bird flew!" << endl;
  36:         }
  37: };
  38: 
  39: class Fish : public Animal
  40: {
  41:     public:
  42:         void Eat()
  43:         {
  44:             cout << "The fish ate!" << endl;
  45:         }
  46:         void Swim()
  47:         {
  48:             cout << "The fish swam!" << endl;
  49:         }
  50: };
  51: 
  52: int main()
  53: {
  54:     Animal *animal1 = new Dog;
  55:     Animal *animal2 = new Bird;
  56:     Animal *animal3 = new Fish;
  57: 
  58: 
  59:     Dog *myDog = (Dog*)animal1;
  60:     myDog->Run();
  61:     Bird *myBird = (Bird*)animal2;
  62:     myBird->Fly();
  63:     Fish *myFish = (Fish*)animal3;
  64:     myFish->Swim();
  65: }
The dog ran!
The bird flew!
The fish swam!

در بالا سه شی از کلاس Animal ایجاد و آنها را بوسیله سه سازنده از کلاسهای مشتق مقدار دهی اولیه کرده ایم (خطوط 56-54). سپس با استفاده از عمل DownCast اشیا ایجاد شده از کلاس Animal را در نمونه هایی از کلاس های مشتق ذخیره می کنیم (خطوط 59، 61 و 63). وقتی این کار را انجام دادیم می توانیم متدهای مخصوص به هر یک از کلاسهای مشتق را فراخوانی کنیم (خطوط 60، 62 و 64).