PDA

View Full Version : آموزش: چند ریختی (Ploymorphism) در #C



firoozi90
پنج شنبه 19 مرداد 1391, 16:32 عصر
در این مقاله قصد داریم یکی از مفاهیم کلیدی موجود در C# را برای شما آموزش دهیم.چند ریختی یکی از مفاهیم اساسی شیء گرایی در C# می باشد که به شما این امکان را می دهد تا در زمان اجرای برنامه متدهای یک کلاس مشتق شده از یک کلاس مبنا را فراخوانی کنید.این قابلیت زمانی بیش از پیش کار آمد بنظر می آید که شما بخواهید گروهی از اشیاء را به یک آرایه نسبت دهید و سپس هریک از متد های آنها را فراخوانی نمایید.ضمنا نیازی نیست که تمامی آنها از یک نوع شیء باشند.البته چنانچه آنها از طریق ارثبری با یکدیگر ارتباط داشته باشند، می توانید اونها را بعنوان یک نوع وارث (inherited type) به آرایه نسبت دهید.در چنین حالتی اگر همه آنها نام متدی با نام مشابهی داشته باشند، اون متد را به ازای هر شیء می توانید صدا بزنید.در این مقاله چگونگی انجام این کار را به شما نشان خواهیم داد.

using System; public class DrawingObject { public virtual void Draw() { Console.WriteLine("I'm just a generic drawing object."); } }

در مثال بالا کلاسی را با نام DrawingObject پیاده سازیم کرده ایم.این کلاس، کلاس مبنای ما خواهد بود بصورتی که سایر اشیاء ما از آن ارث خواهند برد.همانطور که می بینید این کلاس در داخل خود متدی با نام Draw() دارد.ملاحظه می کنی که در تعریف متد Draw() از کلمه کلیدی virtual استفاده شده است که به این معنی است که امکان نادیده گرفتن (override) این متد در کلاس های مشتق شده وجود دارد.به بیانی ساده تر می توان گفت که کلاس های مشتق شده می توانند پیاده سازی های مختلفی از این متد داشته باشند و آن را تغییر دهند.اما عملی که این متد در کلاس DrawingObject انجام می دهد این است که یک عبارت ساده را خروجی کنسول چاپ می کند.

using System; 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."); } }

همانطور که در مثال بالا می بینید، سه کلاس مشتق شده را از کلاس مبنایمان ایجاد می کنیم.هر یک از این کلاس ها از کلاس DrawingObject ارثبری دارند.به کلمه override در تعریف متد Draw() در هریک از این کلاس ها توجه کنید.این کلمه اجازه می دهد تا در زمان اجرا یک متد، متد همنامش را در کلاس مبنا بی اثر کرده و خودش اجرا گردد(البته همانطور که گفته شد در کلاس مبنا این متد باید یک virtual method تعریف شود).توجه داشته باشید که این گونه متد ها باید امضا (signature)، نام و پارامتر های یکسانی با متد اصلی در کلاس مبنا داشته باشند.

حال می خواهیم ببینیم که چگونه می توان از کلاس هایی که در بالا تعریف کردیم برای پیاده سازی چندریختی (polymorphism) استفاده کنیم.

using System; public class DrawDemo { public static int Main( ) { 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; } }
با نگاهی به نمونه برنامه بالا مشاهده خواهد کرد که در متد main() برنامه آرایه ای از اشیاء ایجاد می گردد.اشیائی که در این آرایه (dObj) قرار خواهند گرفت از نوع DrawingObject می باشند که در ابتدا چهار شیء از این نوع به آن مقدار دهی می شوند.

بدلیل آنکه ارتباطی از نوع ارثبری بین کلاس های Line، Circle و Square با کلاس DrawingObject وجود دارد، می توان آنها را به آرایه dObj نسبت داد.در صورت عدم وجود این قابلیت شما می بایست برای هر یک از کلاس های خود، آرایه ای مجزا را ایجاد می کردید.اما ارثبری این امکان را فراهم می کند که اشیاء مشتق شده رفتاری مشابه با کلاس مبنا را از خود نشان دهند که این مسئله باعث ساده تر شدن کار می گردد.

پس از مقدار دهی اولیه آرایه، حلقه foreach ای را میبینید که عناصر موجود در آرایه را یک به یمک پیمایش می کند.در هر بار تکرار این حلقه به ازای هریک از عناصر آرایه dObj ، متد Draw() فراخوانی می گردد.بدلیل وجود قابلیت چندریختی این فراخوانی بر اساس نوع هر شیء در زمان اجرا صورت می گیرد.

همانطور که می بینید نوع اشیاء آرایه dObj از نوع DrawingObject می باشند، اما این مسئله مهم نیست.چراکه کلاس های مشتق شده متد Draw() را از کلاس مبنا (DrawingObject) بی اثر می کنند.این مسئله باعث می شود که در زمان اجرا بجای اجرا شدن متد Draw از کلاس DrawingObject، متد های مربوط به کلاس های مشتق شده اجرا گردند.خروجی حاصل از اجرای برنامه بالا بصورت زیر خواهد بود:

Output: I'm a Line. I'm a Circle. I'm a Square. I'm just a generic drawing object.
همانطور که می بینید متد های Draw() مربوط به هریک از کلاس های مشتق شده یک به یک فراخوانی و اجرا می گردند و در خط آخر نیست متد Draw() مربوط به کلاس مبنا صدا زده می شود.این به این خاطر است که نوع شیء آرایه ما در زمان اجرا برابر با DrawingBoject می شود و در نتیجه متد اصلی Draw() فراخوانی می گردد.

تا اینجا شما باید مفهوم چندریختی در C# را درک کرده باشید.همچنین بتوانید متد هایی از نوع virtual تعریف کرده و سپس از طریق کلاس های مشتق شده از کلاس مبنا ، این متد ها را بی اثر نمایید.ارتباط موجود بین متد های virtual و متد های موجود در کلاس های مشتق شده که آنها را بی اثر می نمایند باعث ایجاد قابلیتی بنام چند ریختی (polymorphism) می گردد که در این مقاله به آن پرداخته شد.

موفق و پیروز باشید

منبع : vsharp-station (http://www.csharp-station.com/Tutorial/CSharp/Lesson09)