PDA

View Full Version : کاربرد delegate ,Interface



green_pm
یک شنبه 26 اردیبهشت 1389, 12:03 عصر
سلام
کاربرد عملی delegate , Interfacer چه موقع است؟

cardano7
یک شنبه 26 اردیبهشت 1389, 16:05 عصر
سلام
در مورد delegate باید بگم که فرض کن یک مجموعه تابع داریم و بسته به انتخاب کاربر یا به هر شکل دیگه یکی از اونا قراره صدا زده بشه. یک delegate همیشه نماینده ی یک تابع(از قبل نامشخص) هست و صدا زدن اون delegate باعث صدا زده شدن تابع مربوطه میشه.
مثلا فرض کن که یک فرمی داریم که در اون از کاربر یک عدد اعشاری دریافت میشه و در کنار TextBox یک ComboBox هم داریم که تعیین می کنه کدوم یکی از این اعمال روی عدد ما انجام بشه:
Tan, Sin, Cos, ArcSin, Log,....
خوب حالا وقتی کاربر روی دکمه ی Calculate می زنه این اعمال چگونه باید تشخیص داده بشند؟
با یک Switch-Case ساده میشه این کار را کرد. اما این روش، روش تمیزی نیست. راه بهتر اینه که یک کلاس تعریف کنیم که دو عضو داره. یکی Delegate هست و دیگری Name که نام تابع نشان داده شده در ComboBox هست. حالا یک آرایه از این کلاس تهیه می کنیم. و اعضای اون را در ComboBox نشون میدیم.
هر وقت که قرار شد تابع صدا زده بشه با یک Search ساده در این آرایه، Delegate مربوطه را پیدا کرده و اون را صدا می زنیم.
در این روش نام هر تابع در کنار خود اون تابع اومده و مهمتر از همه اینه که فقط یک بار از تابع استفاده کردیم. این یعنی برنامه ی ما خیلی تمیز بوده و راحت قابل گسترش هست.

public delegate double MathFunc(double x);

public class FunctionCollection
{
public string Name;
public MathFunc Function;
public FunctionCollection(string Name, MathFunc Function)
{
this.Name = Name;
this.Function = Function;
}
}

FunctionCollection[] funcCollection = new FunctionCollection[]
{
new FunctionCollection("sin",Math.Sin),
new FunctionCollection("cos",Math.Cos),
new FunctionCollection("tan",Math.Tan),
new FunctionCollection("log",Math.Log),
new FunctionCollection("gamma",MyLibrary.Gamma),
};

البته حواستون باشه که یک delegate در C#‎‎‎‎ باید در غالب خاص استفاده بشه. یعنی نوع ورودی هاش و خروجی اش مشخص باشه. در مثال بالا اگر به جای

public delegate double MathFunc(double x);
بنویسم:

public delegate double MathFunc(float x);
بلافاصله در خط

new FunctionCollection("sin",Math.Sin),
یک Error داده میشه چون Math.Sin مقدار double می گیره و نه float
این بر خلاف ++C هست که میشه به شکل بی بند و بار توابع را با آدرسشون صدا زد.
در ++C گفته میشد که ()clrscr به معنی صدا زدن یک تابع هست در حالی که clrscr بدون پرانتز به معنی آدرس حافظه ی اون هست. یعنی یک نفر می تونست مقدار اون را در یک اشاره گر ذخیره کنه و وقتی اسم اون اشاره گر را با پرانتز صدا بزنه اون وقت خود clrscr صدا زده میشه(استفاده ی اشتباه از این قابلیت منجر به اختلال جدی در برنامه می شد).
C#‎‎‎‎ به شکل رسمی و کاملا امن این قابلیت را توسط delegate به کاربران داده.
گاهی هم از delegate ها برای صدا زدن تابعی به کار میره که منشا اصلی اون از ابتدای برنامه معلوم نیست.
ناگفته نمونه که برخی برنامه نویس ها هم از delegate ها برای دور زدن قوانین سطح دسترسی به یک تابع ( private یا Protected ) توسط یک delegate قایل دسترس استفاده می کنند. حالا این که آیا این کار اصولی هست یا نه بماند!

امیدوارم که توضیحاتی که داده باشم شما را راضی کرده باشه.
اگه نکته یی ناگفته مونده دوستان لطفا کمک کنند.

cardano7
یک شنبه 26 اردیبهشت 1389, 16:20 عصر
و اما interafce ها:
جایی به کار میره که قراره یک کلاس را به داشتن یک سری تابع ملزم کنیم. مثلا فرض کن ما دو تا کلاس داریم به نام myMusic و myVideo می خواهیم هر دو اینها ملزم به داشتن توابع Load و Save و Play باشند. مسلما روش پیاده سازی این توابع توسط هر کدام از این کلاس ها متفاوت از دیگری است. و نمیشه در یک کلاس به نام myMedia اونا رو پیاده سازی کرد و از اون کلاس مشتق گرفت:


public class myMusic:myMedia
public class myVideo:myMedia


برای همین در یک Interface این توابع را معرفی می کنیم و وقتی که کلاس از اون Interface مشتق می گیره ملزم به این هست که این توابع را پیاده سازی بکنه. تا اونجایی که من می دونم اون تابع را میشه مستقیم از یک object از جنس خود اون interface هم صدا زد. و کار Interface فقط الزام نیست.
توجه به این دو نکته ضروری هست که:
1- یک کلاس حد اکثر از یک کلاس دیگه می تونه مشتق بشه. و وراثت چندگانه وجود نداره. اما می تونه از 1000 تا Interface مشتق بشه و محدودیتی برای وراثت از Interface ها وجود نداره.
2- یک کلاس می تونه یک متد را پیاده سازی بکنه اما یک Interface فقط می تونه تعریف بکنه و قابلیت پیاده سازی یک متد را نداره.
راستش یادم نیست که در Interface آیا میشه فیلد هم تعریف کرد یا نه!

اکیدا توصیه می کنم که به کلاس های abstract هم نگاهی بیندازید و فرق اون را با interface حتما google کنید.

green_pm
یک شنبه 26 اردیبهشت 1389, 18:25 عصر
ممنون دوست عزیز.
اگه امکانش هست برنامه ای را که در قسمت delegate توضیح دادید را بذاری خیلی ممنون میشم.
فکر میکنم اگه کدشو ببینم بهتر متوجه بشم.

cardano7
یک شنبه 26 اردیبهشت 1389, 22:58 عصر
راستش این مثال رو همین جوری زدم. ولی حالا که گفتید دیدم بدم نمیاد که برنامه ش رو هم بنویسم. چون می خواستم به یک نفر دیگه هم نشون بدم. :D

اَرژنگ
سه شنبه 11 خرداد 1389, 04:17 صبح
و اما interafce ها:
جایی به کار میره که قراره یک کلاس را به داشتن یک سری تابع ملزم کنیم. مثلا فرض کن ما دو تا کلاس داریم به نام myMusic و myVideo می خواهیم هر دو اینها ملزم به داشتن توابع Load و Save و Play باشند. مسلما روش پیاده سازی این توابع توسط هر کدام از این کلاس ها متفاوت از دیگری است. و نمیشه در یک کلاس به نام myMedia اونا رو پیاده سازی کرد و از اون کلاس مشتق گرفت:


public class myMusic:myMedia
public class myVideo:myMedia


برای همین در یک Interface این توابع را معرفی می کنیم و وقتی که کلاس از اون Interface مشتق می گیره ملزم به این هست که این توابع را پیاده سازی بکنه. تا اونجایی که من می دونم اون تابع را میشه مستقیم از یک object از جنس خود اون interface هم صدا زد. و کار Interface فقط الزام نیست.
توجه به این دو نکته ضروری هست که:
1- یک کلاس حد اکثر از یک کلاس دیگه می تونه مشتق بشه. و وراثت چندگانه وجود نداره. اما می تونه از 1000 تا Interface مشتق بشه و محدودیتی برای وراثت از Interface ها وجود نداره.
2- یک کلاس می تونه یک متد را پیاده سازی بکنه اما یک Interface فقط می تونه تعریف بکنه و قابلیت پیاده سازی یک متد را نداره.
راستش یادم نیست که در Interface آیا میشه فیلد هم تعریف کرد یا نه!

اکیدا توصیه می کنم که به کلاس های abstract هم نگاهی بیندازید و فرق اون را با interface حتما google کنید.

وقتی که الزام وجود داشتن متدها را بخواهند بیان کنند از اینترفیس استفاده میشه.
کلاس از اینترفیس مشتق نمیشه، اینترفیسهایه مختلف را پیاده و یا اینکه پشتیبانی میکنه.
دلیل استفاده از وراثت بهره بری از کدی است که موجود بود، نه اینکه الزام وجود داشتن یک سری از قابلیتها. اینترفیس برایه اعلام کردن قابلیتهاست.
مفهوم ارث بری را با پیاده کردن و یا پشتیبانی از قبلیتهایی که یک اینترفیس اعلام میکنه اشتباه نگیرید. ارث بری و پیاده سازی اینترفیسها در جاوا به شکل علنی با کلمه کلیدی implements مشخص است، در سی شارپ سینتکس ارث بری از کلاس و الزام پیاده کردن و اینکه یک اینترفیس پیاده شده یکی هستند برایه همین تازه‌کارها را به اشتباه میندازند.

فرق کلاسهایه ابسترکت و اینترفیس در حد مفهومی است و فرقهایه قابلیتیشان را مقایسه کردن بی‌معنی است.

armsoftpc
پنج شنبه 02 مرداد 1393, 15:24 عصر
با سلام

فرق کلاسهایه ابسترکت و اینترفیس در حد مفهومی است و فرقهایه قابلیتیشان را مقایسه کردن بی‌معنی است.
http://www.codeproject.com/Articles/11155/Abstract-Class-versus-Interface