امیر معصوم بیگی
امیر معصوم بیگی
خواندن ۷ دقیقه·۲ سال پیش

آموزش اینترفیس یا رابط (interface) در سیشارپ ، از توهم یادگیری تا واقعیت



سلام من امیر معصوم بیگی هستم و قصد دارم یه موضوع جالب و بسیار مهم در سیشارپ رو با شما به اشتراک بزارم ، شاید با خودتون بگید که چرا توهم یادگیری در اینترفیس ! واقعیت اینه اگر تازه با اینترفیس آشنا شده باشید و تجربه زیادی در برنامه نویسی نداشته باشید و کورس های آموزش اینترفیس رو مشاهده کنید ، متاسفانه در اکثر کتب و آموزش های تصویری این مبحث به طور کاملا اشتباه آموزش داده میشه ! در واقع فقط بخشی از کارایی اینترفیس گفته میشه و همین باعث میشه وقتی وارد برنامه نویسی های پیشرفته میشید که به شدت از اینترفیس استفاده شده به مشکل شدید میخورید ! همین شد که تصمیم گرفتم این مبحث رو به صورت جامع برای شما باز کنم و توضیح بدم که توضیح عامیانه اینترفیس چیه و استفاده واقعی و کارایی اصلی اون در سیشارپ به چه صورته !

اما اول از همه بزارید بگم قراره بیشتر روی کدوم بخش اینترفیس مانور بدیم (:

ما قراره روی قابلیت تغیر شکل اینترفیس بحث کنیم و بگیم چرا این قابلیت خیلی مهمه و چرا توجه بهش در سیشارپ خیلی اهمیت داره


اما خب اول از این شروع میکنم که به صورت عامیانه و در بیشتر تدریس ها در مورد اینترفیس چی میگن !

اینترفیس :

یک اینترفیس یا رابط یک قرارداد را تعریف می کند. هر کلاس یا ساختاری که آن قرارداد را پیاده سازی می کند باید پیاده سازی اعضای تعریف شده در رابط را ارائه بده .

اما این یعنی چی ! کد زیر رو ببینید که بیشتر در موردش صحبت کنیم

interface ISendEmailHandler { SendEmail(string description); } public class SendEmailHandler : ISendEmailHandler { public SendEmail(string description) { // Write Code } }


در مثال بالا ما یک اینترفیس به نام ISendEmailHandler تعریف کردیم ، این ایترفیس متدی به اسم SendEmail داره ، همونجوری که میبینید ما هیچ پیاده سازی ای برای این متد قرار ندادیم ، دلیلش اینه که ما در اینترفیس ها قرارداد رو تعریف میکنیم نه پیاده سازی ! دلیل اون هم اینه که ما در خیلی از سناریو ها نیاز به یک قابلیتی داریم ولی چگونگی اجرای اون عملکرد برای ما اهمیت چندانی ندارد ! مثلا در این مثال ما کلاس SendEmailHandler رو نوشتیم ، در این کلاس ما فقط نیاز داریم که متدی داشته باشه که با فراخانی متد یک ایمیل ارسال بشه ، اینکه این کلاس چطور اون رو پیاده سازی میکنه برای ما اهمیتی ندارد ، به همین علت اینترفیسی ایجاد میکنیم ، و هر وقتی خواستیم کلاسی این ویژگی رو حتما اجرا کنه این اینترفیس رو به ارث میبره .

اما ویژگی های اینترفیس

  1. اعلان می شوند اما دارای هیچ جزئیات اجرایی نیستند. صرفا عنوان و سیگناچر متد ها و مشخصه ها را تعریف می کنند. کد اجرایی آنها در کلاس هایی که از آن اینترفیس ارث می برند ، نوشته می شود.
  2. مشخصه های آن جزئی و متد های آن جزئی یا مجرد است. مقادیر مشخص نشده اند.
  3. نمی توان آن را مستقیما اینستانس یا همان نمونه سازی کرد. اینترفیس ها برای تعریف مشخصه های مشترک و عملکرد مشابه استفاده می شوند.
  4. کلاس هایی که از یک اینترفیس ارث می برند ، موظف هستند تمام متد ها و مشخصه های آن اینترفیس را پیاده سازی کنند.
  5. اینترفیس ها دسترسی سطح را افزایش می دهند. کد نوشته شده مستقل تر است و قابل استفاده مجدد می باشد.
  6. اینترفیس ها در سی شارپ پیاده سازی مجدد می شوند. یک اینترفیس می تواند توسط چندین کلاس پیاده سازی شود که این بر خلاف استفاده از Absract کلاس هاست که فقط میتوان از یکی از آن ها ارث بری کرد !

با توجه توضیحات بالا ، ما نمیتونیم از اینترفیس نمونه سازی کنیم و صرفا میتونیم ویژگی ها کلاس رو با اون مشخص کنیم و به کلاس بگیم که فلان ویژگی رو حتما داشته باشه !

اما واقعیت همینه ؟

واقعیت اینه که در اکثر آموزش ها تقریبا با کمی تغیر همین مطالب رو به شما میگن و متاسفانه این کاملا ناقصه !

درسته ما برای اینکه یک قرار دادی رو تعین کنیم و بقیه رو مجبور به پیروی از اون کنیم از اینترفیس استفاده میکنیم ، علاوه بر اینکه میتونه چندین تا از این قرار داد ها رو برای یک کلاس تعریف کنی و البته نمیتونی از اینترفیس نمونه تعریف کنی .

اما این همش نیست ! درواقع استفاده از اینترفیس ها و محبوبیت اون در دات نت کاملا به یک ویژگی دیگه که در اکثر آموزش ها به اون پرداخته نمیشه هستش !

اونم قابلیت تغیر شکل ! بزارید به مثال قبل برگردیم و کمی در اون تغیر ایجاد کنیم !

class MainClass { interface ISendEmailHandler { SendEmail(string description); } public class SendEmailHandler1 : ISendEmailHandler { public string Name {get;set;} public SendEmail(string description) { Console.WriteLine(description + &quot Send From SendEmail1&quot) } } public class SendEmailHandler2 : ISendEmailHandler { public string Title {get;set;} public SendEmail(string description) { Console.WriteLine(description + &quot Send From SendEmail2&quot) } } static void Main() { // کد زیر امکان اجرا ندارد و به شما ارور کامپیال میدهد ISendEmailHandler p = new ISendEmailHandler (&quotHello&quot); // Have Err // کد ها زیر بدون هیچ مشکلی اجرا و استفاده میشوند ISendEmailHandler sender1 = new SendEmailHandler1 (); ISendEmailHandler sender2 = new SendEmailHandler2 (&quotHello 2&quot); sender1.SendEmail(&quotHello 1&quot); sender2.SendEmail(&quotHello 2&quot); } }

در مثال بالا یک کلاس جدید ایجاد کردیم و در هر کلاس از ایترفیس ISendEmailHandler استفاده کردیم ، در قسمت Main ابتدا سعی کردیم که یک نمونه از اینترفیس بسازیم که همونجوری که در کد هم نوشته شده به ارور میخوریم پس این کار امکان پذیر نیست ! اما در خط های بعدی در کمال تعجب میبینیم که ما دوباره با همون ساختار کد رو نوشتیم ولی کد هیچ ایرادی ندارد و اجرا میشود ، اما اگر دقت کنین میبینید که در قسمت دوم کد بجای new کردن یک اینترفیس ، از یک کلاس اینستس یا نمونه ساخته میشود ! این یکی از مهم ترین قابلیت های اینترفیس هست که به آن قابلیت تغیرشکل میگویند ! در واقع ایترفیس ها میتونن به کلاس هایی که اون رو نمونه سازی کردن تغیر شکل بدهند و به هر بخش از اون کلاس رو که اون اینترفیس رو پیاده کرده رو دسترسی داشته باشند و از اون استفاده کنن !

که اگر این مثال رو در سیستم خودتون اجرا کنین ، میبینید که شما هیچ دسترسی به Name و Title که پروپرتی های اختصاصی این دو کلاس هستند دسترسی ندارید و فقط به متد SendEmail دسترسی دارید !

نکته ای مهم که اگر بهش دقت نکنید بسیار در مبحث های پیشرفته مثل دپدنسی اینجکشن و وارون وابستگی به مشکل میخورید!

چون اساس کارشون بر همین مبناس ! یعنی بجای اینکه شما یک کلاس رو به عنوان ورودی یک متد یا سازنده قرار بدید ، یک اینترفیس به عنوان ورودی اون متد قرار میگیره ، مثال زیر رو ببینید که بیشتر براتون جا بیفته !

class MainClass { interface ISendEmailHandler { SendEmail(string description); } public class SendEmailHandler1 : ISendEmailHandler { public string Name {get;set;} public SendEmail(string description) { Console.WriteLine(description + &quot Send From SendEmail1&quot) } } public class SendEmailHandler2 : ISendEmailHandler { public string Title {get;set;} public SendEmail(string description) { Console.WriteLine(description + &quot Send From SendEmail2&quot) } } static void Main() { // دو نمونه از کلاس ها ساختیم SendEmailHandler1 sender1 = new SendEmailHandler1 (); SendEmailHandler2 sender2 = new SendEmailHandler2 (&quotHello 2&quot); // حالا ما میتونیم این کلاس رو به متد هندلر در پایین ارسال کنیم و از قابلیت تغیر شکل استفاده کنیم Handler(sender1); Handler(sender2); // } static void Handler(ISendEmailHandler sender) { sender.SendEmail(&quotHello From Handler&quot); } }

همونجور که در مثال بالا میبینید ما یک کلاس رو به متد Handler ارسال کردیم و حالا اون کلاس وقتی به این متد ارسال میشوند خودکار به اینترفیسی که آن را قبلا پیاده سازی کرده تغیر شکل میدهد

این قابلیت کلیدی اینترفیس که به کلاس هایی که اون رو پیاده سازی کرده تبدیل میشود یکی از مهم ترین قابلیت ها در کل سیشارپ محسوب میشه و در صورتی که اون رو درک نکنین در خیلی از مباحث مرتبط باهش دچار مشکل میشید ، و همونجور که گفتم در مورد این قابلیت تغیر شکل معمولا در کورس های آموزشی توضیحی داده نمیشه و وقتی شما آموزشی مثل Asp.net Core میبیند که اساس اون در بسیاری از موارد همین قابلیتی به مشکل درک موضوع میخورید

امیدوارم که این آموزش برای شما بوده مفید باشه :)


اینترفیسstring descriptioncآموزش اصولی اینترفیسinterface
شاید از این پست‌ها خوشتان بیاید