پلی مرفیسم (Polymorphism)
یکی دیگر از مفاهیم اولیه ی شیء گرایی پلی مرفیسم ( چند ریختی ) می باشد. پلی مرفیسم به معنای توانایی استفاده کردن از فرم های مختلف یک نوع است بدون توجه به جزئیات آن .
برای مثال هنگامیکه سیگنال تلفنی شما فرستاده می شود ، از نوع تلفنی که در انتهای خط موجود است خبری ندارد. تلفن انتهای خط ، می خواهد یکی از تلفن های عهد عتیق باشد و یا تلفنی با آخرین امکانات روز .
شرکت مخابرات (!) تنها از نوع پایه ای به نام phone خبر دارد و فرض می کند که هر instance از این نوع می داند که چگونه صدای زنگ تلفن شما را به صدا در آورد. بنابراین شرکت مخابرات از تلفن شما به صورت پلی مرف استفاده می کند.
در عمل پلی مرفیسم هنگامی مفید خواهد بود که بخواهیم گروهی از اشیاء را به یک آرایه نسبت دهیم و سپس متدهای هر یک را فراخوانی کنیم. الزاما این اشیاء از یک نوع نخواهند بود.
نحوه ی ایجاد متدهای پلی مرفیک :
برای ایجاد متدی که نیاز است تا پلی مرفیسم را پشتیبانی نماید ، تنها کافی است آنرا از نوع virtual در کلاس پایه تعریف کنیم. مثال :
فرض کنید تابع DrawWindow در کلاس Window تعریف شده است. برای ایجاد قابلیت پلی مرفیسم در آن به صورت زیر عمل می شود :
کد:
public virtual void DrawWindow( )
در این حالت هر کلاسی که از Window مشتق شود ، مجاز است نگارش خاص خودش را از DrawWindow ارائه کند. در این صورت در کلاسی که از کلاس پایه ی ما ارث می برد ، تنها کافی است که کلمه ی کلیدی override را قبل از نام تابع مذکور ذکر نماییم.
یک مثال کامل :
کد:
using System;
public class DrawingObject
{
public virtual void Draw()
{
Console.WriteLine("I'm just a generic drawing object.");
}
}
public class Line : DrawingObject
{
public override void Draw()
{
Console.WriteLine("I'm a Line.");
}
}
public class Circle : DrawingObject
{
public override void Draw()
{
Console.WriteLine("I'm a Circle.");
}
}
public class Square : DrawingObject
{
public override void Draw()
{
Console.WriteLine("I'm a Square.");
}
}
public class DrawDemo
{
public static int Main(string[] args)
{
DrawingObject[] dObj = new DrawingObject[4];
dObj[0] = new Line();
dObj[1] = new Circle();
dObj[2] = new Square();
dObj[3] = new DrawingObject();
foreach (DrawingObject drawObj in dObj)
{
drawObj.Draw();
}
return 0;
}
}
کلاس DrawingObject ، کلاسی پایه برای تمام کد ما که از آن به ارث می برد ، می باشد. متد Draw در آن با کلمه ی کلیدی virtual معرفی شده است. یعنی تمام کلاس های فرزند این کلاس والد می توانند این متد را override کنند ( تحریف کردن و یا تحت الشعاع قرار دادن هم ترجمه شده است! ).
در ادامه سه کلاس تعریف شده اند که تمامی آنها از کلاس مبنا ارث می برند و تابع Draw را تحریف کرده اند (!). با استفاده از کلمه ی کلیدی override می توان تابع مجازی کلاس مبنا را با تعریفی جدید در زمان اجرای برنامه ارائه داد. تحریف شدن تنها زمانی رخ می دهد که کلاس ، توسط ریفرنس کلاس مبنا مورد ارجاع واقع شده باشد.
و در متد Main برنامه از این کلاس ها در عمل استفاده گردیده است. در متد Main ، آرایه ای از نوع DrawingObject تعریف و مقدار دهی اولیه شده است تا بتواند 4 شیء از نوع این کلاس را در خودش ذخیره کند.
بدلیل رابطه ی ارث بری موجود می توان آرایه ی dObj را با نوع هایی از کلاس های Line ، Circle و Square مقدار دهی کرد (همانند کدهای بعدی متد Main ) . اگر ارث بری در اینجا وجود نمی داشت می بایست به ازای هر کلاس یک آرایه تعریف می شد.
سپس از حلقه ی زیبای foreach برای حرکت در بین اعضای این آرایه استفاده گردیده است. در اینجا هر شیء متد خاص خودش را در مورد Draw فراخوانی می کند و نتیجه را روی صفحه نمایش خواهد داد.
خروجی نهایی به صورت زیر خواهد بود :
کد:
Output:
I'm a Line.
I'm a Circle.
I'm a Square.
I'm just a generic drawing object.
__________________