چند ریختی (Polymorphism)

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

   1: using System;
   2: 
   3: class Animal
   4: {
   5:     public virtual void Eat()
   6:     {
   7:         Console.WriteLine("The animal ate!");
   8:     }
   9: }
  10: 
  11: class Dog : Animal
  12: {
  13:     public override void Eat()
  14:     {
  15:         Console.WriteLine("The dog ate!");
  16:     }
  17: }
  18: 
  19: class Bird : Animal
  20: {
  21:     public override void Eat()
  22:     {
  23:         Console.WriteLine("The bird ate!");
  24:     }
  25: }
  26: 
  27: class Fish : Animal
  28: {
  29:     public override void Eat()
  30:     {
  31:         Console.WriteLine("The fish ate!");
  32:     }
  33: }
  34: 
  35: class Program
  36: {
  37:     public static void Main()
  38:     {
  39:         Dog myDog = new Dog();
  40:         Bird myBird = new Bird();
  41:         Fish myFish = new Fish();
  42:         Animal myAnimal = new Animal();
  43:    
  44:         myAnimal.Eat();
  45: 
  46:         myAnimal = myDog; 
  47:         myAnimal.Eat();   
  48:         myAnimal = myBird;
  49:         myAnimal.Eat();   
  50:         myAnimal = myFish;
  51:         myAnimal.Eat();   
  52:     }
  53: }
The animal ate!
The dog ate!
The bird ate!
The fish ate!

همانطور که مشاهده می‌کنید 4 کلاس مختلف تعریف کرده‌ایم. Animal کلاس پایه است و سه کلاس دیگر از آن مشتق می‌شوند. هر کلاس متد Eat() مربوط به خود را دارد. نمونه‌ای از هر کلاس ایجاد کرده‌ایم (42-39). حال متد Eat() را به وسیله نمونه ایجاد شده از کلاس Animal به صورت زیر فراخوانی می‌کنیم :

Animal myAnimal = new Animal();

myAnimal.Eat();

در مرحله بعد چندریختی روی می‌دهد. همانطور که در مثال بالا مشاهده می‌کنید شی Dog را برابر نمونه ایجاد شده از کلاس Animal قرار می‌دهیم (خط 46) و متد Eat() را بار دیگر فراخوانی می‌کنیم. حال با وجود اینکه ما از نمونه کلاس Animal استفاده کرده‌ایم ولی متد Eat() کلاس Dog فراخوانی می‌شود. این به دلیل تأثیر چند ریختی است.

سپس دو شیء دیگر (Bird و Fish) را برابر نمونه ایجاد شده از کلاس Animal قرار می‌دهیم و متد Eat() مربوط به هر یک را فراخوانی می‌کنیم. (خطوط 51-48) به این نکته توجه کنید که وقتی در مثال بالا اشیاء را برابر نمونه کلاس Animal قرار می‌دهیم ازعمل Cast استفاده نکرده‌ایم چون این کار (cast) وقتی که بخواهیم یک شیء از کلاس مشتق (مثلاً Dog) را در شیی از کلاس پایه (Animal) ذخیره کنیم لازم نیست. همچنین می‌توان کلاس Animal را با سازنده هر کلاس مشتق دیگر مقدار دهی اولیه کرد :

Animal myDog = new Dog();
Animal myBird = new Bird();
Animal myFish = new Fish();

myDog.Eat();
myBird.Eat();
myFish.Eat();

اجازه دهید که برنامه بالا را اصلاح کنیم تا مفهوم چند ریختی را بهتر متوجه شوید :

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

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

((Dog)animal1).Run();
((Bird)animal2).Fly();
((Fish)animal3).Swim();

از چند ریختی می‌توان در رابط‌ها هم استفاده کرد. به کد زیر توجه کنید :

   1: using System;
   2: 
   3: interface IAnimal
   4: {
   5:     void Eat();
   6: }
   7: 
   8: class Dog : IAnimal
   9: {
  10:     public void Eat()
  11:     {
  12:         Console.WriteLine("The dog ate!");
  13:     }
  14: }
  15: 
  16: class Bird : IAnimal
  17: {
  18:     public void Eat()
  19:     {
  20:         Console.WriteLine("The bird ate!");
  21:     }
  22: }
  23: 
  24: class Fish : IAnimal
  25: {
  26:     public void Eat()
  27:     {
  28:         Console.WriteLine("The fish ate!");
  29:     }
  30: }
  31: 
  32: class Program
  33: {
  34:     public static void Main()
  35:     {
  36:         IAnimal myDog = new Dog();
  37:         IAnimal myBird = new Bird();
  38:         IAnimal myFish = new Fish();
  39: 
  40:         myDog.Eat();
  41:         myBird.Eat();
  42:         myFish.Eat();
  43:     }
  44: }
The dog ate!
The bird ate!
The fish ate!

تسلط کامل بر چند ریختی و وراثت برای درک بهتر دات نت ضروری است.