واسطها (Interfaces)
در اين درس با واسطها در زبان C# آشنا خواهيم شد. اهداف اين درس بشرح زير ميباشند :
1- آشنايي با مفهوم كلي واسطها
2- تعريف يك واسط
3- استفاده از يك interface
4- پيادهسازي ارثبري در interface ها
5- نكات مهم و پيشرفته
6- مثالي كاربردي از واسطها
7- منابع مورد استفاده
واسطها از لحاظ ظاهري بسيار شبيه به كلاس هستند با اين تفاوت كه داراي هيچ گونه پيادهسازي نميباشند. تنها چيزي كه در interface به چشم ميخورد
تعاريفي نظير رخدادها، متدها، انديكسرها و يا property ها
است. يكي از دلايل اينكه واسطها تنها
داراي تعاريف هستند و پيادهسازي ندارند آنست كه يك interface ميتوان
توسط چندين كلاس يا property مورد
ارثبري قرار گيرد، از اينرو هر كلاس
يا property خواستار
آنست كه خود به پيادهسازي اعضا بپردازد.
حال بايد
ديد چرا با توجه به اينكه interface ها
داراي پيادهسازي نيستند مورد استفاده قرار ميگيرند
يا بهتر بگوئيم سودمندي استفاده از interface ها در
چيست؟ تصور كنيد كه در يك برنامه با مولفههايي
سروكار داريد كه متغيرند ولي داراي فيلدها يا متدهايي
با نامهاي يكساني هستند و بايد نام اين متدها نيز يكسان باشد. با استفاده از يك interface مناسب
ميتوان تنها متدها و يا فيلدهاي مورد نظر را اعلان نمود و سپس
كلاسها و يا property هاي
مورد از آن interface ارثبري
نمايند. در اين حالت تمامي
كلاسها و property ها
داراي فيلدها و يا متدهايي همنام هستند ولي هر يك پيادهسازي
خاصي از آنها را اعمال مينمايند.
نكته مهم ديگر درباره interface ها،
استفاده و كاربرد آنها در برنامههاي بزرگي است كه برنامهها و يا اشياؤ مختلفي در تماس و تراكنش (transact) هستند.
تصور كنيد كلاسي در يك برنامه با كلاسي
ديگر در برنامهاي ديگر در ارتباط باشد. فرض كنيد اين كلاس متدي دارد كه مقداري از نوع int بازميگرداند. پس از مدتي
طراح برنامه به اين نتيجه ميرسد كه استفاده
از int پاسخگوي مشكلش نيست و
بايد از long استفاده
نمايد. حال شرايط را در نظر
بگيريد كه براي تغيير يك چنين مسئله سادهاي چه مشكل بزرگي پيش خواهد آمد. تمامي فيلدهاي مورتبط با اين متد بايد تغيير داده شوند. در ضمن از
مسئله side effect نيز نميتوان
چشم پوشي كرد.( تاثيرات ناخواسته و غير منتظره و يا به عبارتي پيش بيني نشده كه متغير يا فيلدي بر روي متغير يا فيلدي ديگر اعمال
ميكند، در اصطلاح side effect گفته ميشود.) حال فرض كنيد كه
در ابتدا interface اي
طراحي شده بود. درصورت اعمال
جزئيترين تغيير در برنامه مشكل تبديل int به long قابل
حل بود، چراكه كاربر يا برنامه و
در كل user برنامه
در هنگام استفاده از يك interface با پيادهسازي پشت پرده آن كاري ندارد و يا بهتر بگوئيم امكان دسترسي
به آن را ندارد. از اينرو اعمال تغييرات
درون آن تاثيري بر رفتار كاربر نخواهد داشت و حتي كاربر از آن مطلع
نيز نميشود. در مفاهيم كلي شيء گرايي، interface ها
يكي از مهمترين و كاربردي ترين اجزاء هستند
كه در صورت درك صحيح بسيار مفيد واقع ميشوند. يكي از مثالهاي
مشهود درباره interface ها
(البته در سطحي پيشرفته تر و بالاتر) رابطهاي كاربر
گرافيكي (GUI) هستند.
كاربر تنها با اين رابط سروكار دارد و كاري به نحوه عمليات
پشت پرده آن ندارد و اعمال تغييرات در پيادهسازي interface كاربر
را تحت تاثير قرار نميدهد.
از ديدگاه تكنيكي، واسطها بسط مفهومي هستند كه از آن به عنوان انتزاع (Abstract) ياد ميكنيم.
در كلاسهاي انتزاعي (كه با كلمه كليد abstract مشخص ميشدند.)
سازندة كلاس قدر بود تا فرم كلاس خود را مشخص نمايد : نام متدها،
نوع بازگشتي آنها و تعداد و نوع پارامتر آنها، اما بدون پيادهسازي بدنه متد. يك interface همچنين
ميتواند داراي فيلدهايي باشد كه تمامي آنها static و final هستند. يك interface تنها
يك فرم كلي را بدون پيادهسازي به نمايش ميگذارد.
از اين ديدگاه، يك واسط بيان ميدارد كه : " اين فرم كلي است
كه تمامي كلاسهايي كه اين واسط را
پيادهسازي ميكنند، بايد آنرا داشته باشند." از سوي ديگر كلاسها و اشياء ديگري كه از كلاسي كه از يك واسط مشتق شده استفاده
ميكنند، ميدانند كه اين كلاس
حتماً تمامي متدها و اعضاي واسط را پيادهسازي ميكند و ميتوانند
به راحتي از آن متدها و اعضا استفاده نمايند. پس به طور كلي ميتوانيم بگوئيم كه واسطها بمنظور ايجاد يك پروتكل (protocol) بين
كلاسها مورد استفاده قرار ميگيرند.
(همچنان كه برخي از زبانهاي برنامهسازي بجاي استفاده از كلمه كليدي interface از protocol استفاده
مينمايند.)
به دليل اينكه كلاسها و ساختارهايي
كه از interface ها ارثبري
ميكنند موظف به پيادهسازي و تعريف آنها هستند،
قانون و قاعدهاي در اين باره ايجاد ميگردد. براي مثال اگر كلاس A از واسط IDisposable ارثبري
كند، اين ضمانت بوجود ميآيد كه كلاس A داراي متد Dispose() است، كه تنها عضو interface نيز ميباشد. هر كدي كه ميخواهد
از كلاس A استفاده كند، ابتدا چك مينمايد كه آيا كلاس A واسط IDisposable را پيادهسازي نموده يا خير. اگر پاسخ مثبت باشد آنگاه كد متوجه ميشود كه ميتواند از متد A.Dispose() نيز استفاده
نمايد. در زير نحوه اعلان يك واسط نمايش داده شده است.
|
كد: |
|
interface
IMyInterface |
در اين مثال نحوه اعلان واسطي با نام IMyInterface نشان داده شده است. يك
قاعده (نه قانون!) براي نامگذاري واسطها آنست كه نام واسطها را با "I" آغاز
كنيم كه اختصار كلمه interface است. در interface اين
مثال تنها يك متد وجود دارد. اين متد ميتوان هر متدي با انواع
مختلف پارامترها و
نوع بازگشتي باشد. توجه نماييد همانطور كه گفته شد اين متد داراي
پيادهسازي نيست و
تنها اعلان شده است. نكته ديگر كه بايد به ان توجه كنيد آنست كه
اين متد به جاي داشتن
{} به عنوان بلوك خود، داراي ; در انتهاي اعلان خود ميباشد. علت اين امر آنست كه interface تنها
نوع بازگشتي و پارامترهاي متد را مشخص مينمايد و كلاس يا شياي كه از آن ارث ميبرد بايد
آنرا پيادهسازي نمايد. مثال زير نحوه استفاده از اين واسط را نشان ميدهد.
مثال 1-13 : استفاده از واسطها و ارثبري از آنها
|
كد: |
|
class
InterfaceImplementer : IMyInterface |
در
اين مثال، كلاس InterfaceImplementer همانند
ارثبري از يك كلاس، از واسط IMyInterface ارثبري كرده است. حال كه
اين كلاس از واسط
مورد نظر ارثبري كرده است، بايد، توجه نماييد بايد، تمامي اعضاي آنرا پيادهسازي كند. در اين
مثال اين عمل با پيادهسازي تنها عضو واسط يعني متد MethodToImplement() انجام گرفته است. توجه
نماييد كه پيادهسازي متد بايد دقيقا از لحاظ نوع بازگشتي و تعداد و نوع
پارامترها شبيه به اعلان موجود در واسط باشد، كوچكترين تغييري باعث ايجاد
خطاي كامپايلر ميشود. مثال زير نحوه ارثبري واسطها از يكديگر نيز نمايش داده شده است.
مثال 2-13 : ارثبري واسطها از يكديگر
|
كد: |
|
using
System; |

انجام پروژه های برنامه نویسی