📜 قراردادهای کدنویسی در #C: راهنمای کامل اینترفیسها (Interfaces)
چطور میتونیم برای کلاسهامون یه "قرارداد" تعریف کنیم و بگیم "هر کلاسی که میخواد با من کار کنه، باید این قابلیتها رو داشته باشه"؟
ابزار اصلی ما برای این کار در دنیای شیءگرایی، اینترفیس (Interface) هست. اینترفیسها ستون فقرات معماریهای تمیز، انعطافپذیر و تستپذیر هستن.
1️⃣ اینترفیس چیست؟ یک قرارداد، بدون پیادهسازی
اینترفیس فقط رفتار (Behavior) رو تعریف میکنه، نه وضعیت (State). یعنی فقط امضای متدها و پراپرتیها رو داره، نه فیلدهای داده و نه بدنه پیادهسازی برای اعضاش.
تفاوتهای کلیدی با کلاس:
🔹 فقط توابع (متد، پراپرتی، ایونت، ایندکسر) را تعریف میکند، نه فیلدها.
🔹 اعضایش به صورت پیشفرض public و abstract هستند.
🔹 یک کلاس میتواند چندین اینترفیس را پیادهسازی کند (برخلاف وراثت از کلاس که فقط یکیه).
مثال (اینترفیس IEnumerator):
public interface IEnumerator
{
bool MoveNext();
object Current { get; }
void Reset();
}
2️⃣ پیادهسازی اینترفیس: امضای قرارداد
وقتی یه کلاس، اینترفیسی رو پیادهسازی میکنه، قول میده که برای تمام اعضای اون اینترفیس، یک پیادهسازی public ارائه بده.
internal class Countdown : IEnumerator
{
int count = 11;
public bool MoveNext() => count-- > 0;
public object Current => count;
public void Reset() { throw new NotSupportedException(); }
}
حالا میتونید یک نمونه از Countdown رو در متغیری از نوع IEnumerator بریزید:
IEnumerator e = new Countdown();
while (e.MoveNext())
{
Console.Write(e.Current + " "); // 10 9 8 7 6 5 4 3 2 1 0
}
3️⃣ جادوی پیادهسازی صریح (Explicit Implementation) 🎭
حالا اگه یه کلاس، دو تا اینترفیس رو پیادهسازی کنه که متدهایی با اسم یکسان ولی امضای متفاوت دارن، چی میشه؟ یا اگه بخوایم یه متد از اینترفیس رو از دید عمومی کلاس مخفی کنیم؟
اینجا پای پیادهسازی صریح (Explicit Implementation) به میدون باز میشه. در این حالت، شما اسم اینترفیس رو قبل از اسم متد میارید.
مثال (حل تداخل):
interface I1 { void Foo(); }
interface I2 { int Foo(); }
public class Widget : I1, I2
{
public void Foo() // پیادهسازی پیشفرض برای I1
{
Console.WriteLine("Widget's implementation of I1.Foo");
}
// پیادهسازی صریح برای حل تداخل با I1.Foo
int I2.Foo()
{
Console.WriteLine("Widget's implementation of I2.Foo");
return 42;
}
}نکته حیاتی: ⚠️ متدی که به صورت صریح پیادهسازی شده، دیگه به صورت عمومی در دسترس نیست. برای صدا زدنش، باید اول آبجکت رو به اون اینترفیس خاص کست کنید:
Widget w = new Widget();
w.Foo(); // I1.Foo صدا زده میشه
((I1)w).Foo(); // I1.Foo صدا زده میشه
((I2)w).Foo(); // I2.Foo صدا زده میشه
🤔 حرف حساب و تجربه شما
اینترفیسها، اساس طراحیهای ماژولار، تستپذیر و مبتنی بر اصول SOLID هستن.
🔖 هشتگها:
#CSharp #DotNet #OOP #Interface #CleanCode