آموزش سی شارپ c# درس سیزدهم

 
ارسال شده در تاریخ 1392/7/22 توسط admin در زمینه آموزش سی شارپ
 
درس سیزدهم - واسطها (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
{
void MethodToImplement();
}
 
در این مثال نحوه اعلان واسطی با نام IMyInterface نشان داده شده است . یک قاعده ) نه قانون (! برای نامگذاری واسطها آنست که نام واسطها را با "I" آغاز کنیم که اختصار کلمه interface است . در interface این مثال تنها یک متد وجود دارد . این متد می توان هر متدی با انواع مختلف پارامترها و نوع بازگشتی باشد . توجه نمایید همانطور که گفته شد این متد دارای پیاد ه سازی
نیست و تنها اعلان شده است . نکته دیگر که باید به ان توجه کنید آنست که این متد به جای داشتن {} به عنوان بلوی خود، دارای ; در انتهای اعلان خود میباشد . علت این امر آنست که interface تنها نوع بازگشتی و پارامترهای متد را مشخص مینماید و کلاس یا شی ای که از آن ارث میبرد باید آنرا پیاده سازی نماید . مثال زیر نحوه استفاده از این واسط را نشان می دهد .
 
مثال : 13-1 استفاده از واسطها و ارث بری از آنها
class InterfaceImplementer : IMyInterface
{
static void Main()
{
InterfaceImplementer iImp = new InterfaceImplementer(); iImp.MethodToImplement();
}
public void MethodToImplement()
{
Console.WriteLine("MethodToImplement() called.");
 
 
}
}
در این مثال، کلاس InterfaceImplementer همانند ار ث بری از یک کلاس، از واسط IMyInterface ارث بری کرده است . حال که این کلاس از واسط مورد نظر ار ثبری کرده است، باید، توجه نمایید باید، تمامی اعضای آنرا پیاده سازی کند . در این مثال این عمل با پیاده سازی تنها عضو واسط یعنی متد MethodToImplement() انجام گرفته است . توجه نمایید که پیاده سازیwww.CProje.ir
متد باید دقیقا از لحاظ نوع بازگشتی و تعداد و نوع پارامترها شبیه به اعلان موجود در واسط باشد، کوچکترین تغییری باعث ایجاد خطای کامپایلر میشود . مثال زیر نحوه ارث بری واسطها از یکدیگر نیز نمایش داده شده است .
 
مثال : 13-2 ارث بری واسطها از یکدیگر
using System;
 
interface IParentInterface
{
void ParentInterfaceMethod();
}
 
interface IMyInterface : IParentInterface
{
void MethodToImplement();
}
 
class InterfaceImplementer : IMyInterface
{
static void Main()
{
InterfaceImplementer iImp = new InterfaceImplementer(); iImp.MethodToImplement(); iImp.ParentInterfaceMethod();
}
 
public void MethodToImplement()
{
Console.WriteLine("MethodToImplement() called.");
}
 
public void ParentInterfaceMethod()
{
Console.WriteLine("ParentInterfaceMethod() called.");
}
}
 
مثال 13-2 دارای 2 واسط است : یکی IMyInterface و واسطی که از آن ارث می برد یعنی .IParentInterface هنگامیکه واسطی از واسط دیگری ار ث بری می کند، کلاس یا ساختاری که این واسطها را پیاده سازی می کند، باید تمامی اعضای واسطهای موجود در سلسله مراتب ار ث بری را پیاده سازی نماید . در مثال 13-2 ، چون کلاس InterfaceImplementer از واسط IMyInterface ار ث بری نموده، پس از واسط IParentInterface نیز ار ث بری دارد، از اینرو باید کلیه اعضای این دو واسط را پیاده سازی نماید .
 
 
چند نکته مهم :
 
-1 با استفاده از کلمه کلید interface در حقیقت یک نوع مرجعی (Reference Type) جدید ایجاد نموده اید .
-2 از لحاظ نوع ارتباطی که واسطها و کلاسها در ار ث بری ایجاد می نمایند باید به این نکته اشاره کرد که، ار ثبری از کلاس رابطه " است " یا " بودن (is-a relation) " را ا یجاد میکند ) ماشین یک وسیله نقلیه است ( ولی ارث بری از یک واسط یا interface نوع خاصی از رابطه، تحت عنوان " پیا دهسازی (implement relation) " را ایجاد می کند ") . می توان ماشین را با وام بلند مدت خرید " که در این جمله ماشین می تواند خریداری شدن بوسیله وام را پیاده سازی کند (. -3 فرم کلی اعلان interface ها بشکل زیر است :
[attributes] [access-modifier] interface interface-name [:base- list]{interface-body}
که در اعضای آن بشرح زیر می باشند : صفتهای واسط attributes :
سطح دسترسی به واسط از قبیل public یا access-modifiers : private نام واسط interface-name :
لیست واسطهایی که این واسط آنها را بسط می دهد :base-list : . بدنه واسط که در آن اعضای آن مشخص میشوند Interface-body : توجه نمایید که نمی توان یک واسط را بصورت virtual اعلان نمود .
-4 هدف از ایجاد یک interface تعیین توانائیهاییست که می خواهیم در یک کلاس وجود داشته باشند . -5 به مثالی در زمینه استفاده از واسطها توجه کنید :
فرض کنید می خواهید واسطی ایجاد نمایید که متدها و property های لازم برای کلاسی را که می خواهد قابلیت خواندن و نوشتن از / به یک پایگاه داده یا هر فایلی را داشته باش د، توصیف نماید . برای این منظور می توانید از واسط IStorable استفاده نمایید .
در این واسط دو متد Read() و Write() وجود دارند که در بدنه واسط تع ریف میشوند ی
interface IStorable
{
void Read( ); void Write(object);
}
حال می خواهید کلاسی با عنوان Document ایجاد ن مایید که این کلاس باید قابلیت خواندن و نوشتن از / به پایگاه داده را داشته باشد، پس میتوانید کلاس را از روی واسط IStorable پیاده سازی کنید .
public class Document : IStorable
{
public void Read( ) {...}
public void Write(object obj) {...} // ...
}
حال بعنوان طراح برنامه، شما وظیفه داری تا به پیاده سازی این واسط بپردازید، بطوریکه کلیه نیازهای شما را برآورده نماید . نمونهای از این پیاده سازی در مثال 13-3 آورده شده است .
 
 
مثال : 13-3 پیا دهسازی واسط و ار ثبری - مثال کاربردی
using System;
 
اعلان // interface
interface IStorable
{
void Read( );
void Write(object obj); int Status { get; set; }
}
 
public class Document : IStorable
{
public Document(string s)
{
Console.WriteLine("Creating document with: {0}", s);
}
 
public void Read( )
{
Console.WriteLine("Implementing the Read Method for IStorable");
}
 
public void Write(object o)
{
Console.WriteLine("Implementing the Write Method for IStorable");
}
 
public int Status
{ get
{
return status;
} set
{
status = value;
}
}
private int status = 0;
}
 
public class Tester
{
static void Main( )
{
Document doc = new Document("Test Document"); doc.Status = -1; doc.Read( );
Console.WriteLine("Document Status: {0}", doc.Status);
 
 IStorable isDoc = (IStorable) doc; isDoc.Status = 0; isDoc.Read( );
Console.WriteLine("IStorable Status: {0}", isDoc.Status);
}
}
 
خروجی برنامه نیز بشکل زیر است :
Output:
Creating document with: Test Document Implementing the Read Method for IStorable Document Status: -1
Implementing the Read Method for IStorable IStorable Status: 0
 
-6 در مثال فوق توجه نمایید که برای متدها واسط IStorable هیچ سطح دسترسی public,private) و (... در نظر گرفته نشده است . در حقیقت تعیین سطح دسترسی باعث ایجاد خطا می شود چراکه هدف اصلی از ایجاد یک واسط ایجاد شیء است که تمامی اعضای آن برای تمامی کلاسها قابل دسترسی باشند .
-7 توجه نمایید که از روی یک واسط نم یتوان نمونه ای جدید ایجاد کرد بلکه باید کلاسی از آن ار ثبری نماید .
-8 کلاسی که از واسط ار ث بری می کند باید تمامی متدهای آنرا دقیقا همان گونه که در واسط مشخص شده پیاده سازی نماید . به بیان کلی، کلاسی که از یک واسط ارث می برد، فرم و ساختار کلی خود را از واسط می گیرد و نحوه رفتار و پی ادهسازی آنرا خود انجام میدهد .
 
خلاصه :
در این درس با مفاهیم کلی و اصلی درباره واسطها آشنا شدی د . هم اکنون می دانید که واسطها چه هستند و سودمندی استفاده از آنها چیست . همچنین نحوه پیا دهسازی واسط و ارث بری از آنرا آموختید .
 
مبحث واسطها بسیار گسترده و مهم است و امید است در بخشهای آینده در سایت، بتوانم تمامی مطالب را بطور حرف های و کامل در اختیار شما قرار دهم .
Copyright © 2014 icbc.ir