021-88881776

آموزش شی‌گرایی در سی شارپ

در این مقاله، ما قصد داریم با رویکردی گام به گام به بررسی جامع موضوع شی‌گرایی در سی شارپ بپردازیم. هدف از این آموزش C#، ارائه مفاهیم از سطح مبتدی تا پیشرفته به شکلی ساده و قابل فهم است تا هم تازه‌کاران و هم برنامه‌نویسان با تجربه بتوانند از آن بهره ببرند. در ادامه، با مرور نکات اصلی شی‌گرایی در سی شارپ مانند معرفی کلاس‌ها و اشیاء، ویژگی‌ها و متدها، سازنده‌ها و دمرهای سازنده، وراثت، چندریختی، انتزاع و پیاده‌سازی رابط‌ها، شما را در درک بهتر این مفاهیم یاری خواهیم کرد.

شی‌گرایی در سی شارپ

در شی‌گرایی در سی شارپ، برنامه‌نویسی به گونه‌ای طراحی می‌شود که کدها به اجزای کوچکتر، مستقل و منظم تقسیم شوند. هر یک از این اجزا معمولاً به صورت کلاس‌ها تعریف می‌شوند که با یکدیگر تعامل دارند و این امر باعث می‌شود تا پروژه‌های نرم‌افزاری بزرگ به بخش‌های قابل مدیریت و نگهداری تقسیم شوند. در ادامه به توضیح بیشتر مفاهیم کلیدی این رویکرد می‌پردازیم:

تقسیم‌بندی برنامه به اشیاء و کلاس‌ها

در این سبک برنامه‌نویسی، هر کلاس نمایانگر یک موجودیت واقعی یا مفهومی است. به عنوان مثال، در یک نرم‌افزار مدیریت فروش، کلاس‌هایی مانند Customer (مشتری)، Product (محصول) و Order (سفارش) تعریف می‌شوند. هر کلاس شامل ویژگی‌هایی است که خصوصیات موجودیت مربوطه را نشان می‌دهد و متدهایی که عملیات یا رفتارهای مربوط به آن موجودیت را پیاده‌سازی می‌کند.

ویژگی‌های اصلی شی‌گرایی در سی شارپ

1. کپسوله‌سازی (Encapsulation)

تعریف: کپسوله‌سازی به معنای مخفی‌سازی جزئیات پیاده‌سازی یک کلاس از دنیای بیرون است. به کمک این ویژگی، داده‌های حساس یا داخلی کلاس از دسترسی مستقیم خارجی‌ها محافظت می‌شود.
مزایا:
افزایش امنیت داده‌ها
جلوگیری از تغییرات ناخواسته
امکان کنترل دقیق بر روی عملیات خواندن و نوشتن داده‌ها از طریق متدها و خواص (Properties)
مثال: استفاده از دسترسی‌دهنده‌های private، protected و public در تعریف اعضای کلاس، که کنترل دقیق دسترسی به متغیرها و متدهای کلاس را فراهم می‌کند.

2. وراثت (Inheritance)

تعریف: وراثت به کلاس‌های جدید اجازه می‌دهد تا ویژگی‌ها و رفتارهای یک کلاس موجود (کلاس پایه) را به ارث ببرند. این امر موجب استفاده مجدد از کد و افزایش خوانایی و کاهش تکرار می‌شود.
مزایا:
کاهش میزان کد نویسی
امکان ایجاد سلسله مراتب منطقی بین کلاس‌ها
تسهیل در نگهداری و به‌روزرسانی کدها
مثال: یک کلاس Vehicle می‌تواند شامل ویژگی‌ها و متدهای عمومی وسایل نقلیه باشد و کلاس‌های مشتق مانند Car و Bike از آن وراثت بگیرند و ویژگی‌های خاص خود را اضافه کنند.

3. چندریختی (Polymorphism)

تعریف: چندریختی به توانایی استفاده از یک واسط یا متد به روش‌های متفاوت در کلاس‌های مختلف اطلاق می‌شود. به عبارت دیگر، یک متد در کلاس پایه می‌تواند در کلاس‌های مشتق رفتارهای متفاوتی داشته باشد.
مزایا:
امکان طراحی کدهای منعطف و قابل توسعه
تسهیل در تغییرات آتی نرم‌افزار
بهبود استفاده مجدد از کد از طریق متدهای مشترک با پیاده‌سازی‌های مختلف
مثال: تعریف یک متد Draw() در کلاس پایه Shape که در کلاس‌های مشتق مانند Circle و Rectangle به گونه‌ای متفاوت پیاده‌سازی شود تا هر شکل به صورت مناسب رسم گردد.

4. انتزاع (Abstraction)

تعریف: انتزاع یعنی تمرکز بر ویژگی‌ها و رفتارهای مهم یک موجودیت و نادیده گرفتن جزئیات پیاده‌سازی غیرضروری. این مفهوم معمولاً با استفاده از کلاس‌های انتزاعی (Abstract Classes) و رابط‌ها (Interfaces) پیاده‌سازی می‌شود.
مزایا:
ساده‌سازی پیچیدگی‌های نرم‌افزار
افزایش قابلیت فهم و نگهداری کد
تسهیل در تغییر و به‌روزرسانی پیاده‌سازی‌ها بدون تاثیر بر روی واسط‌های عمومی
مثال: تعریف یک کلاس انتزاعی Employee که متد انتزاعی Work() در آن مشخص شده و کلاس‌های مشتق مانند Developer یا Manager به تفصیل پیاده‌سازی‌های مربوط به خود را ارائه می‌دهند.

اهمیت شی‌گرایی در سی شارپ

با استفاده از مفاهیم شی‌گرایی در سی شارپ، توسعه‌دهندگان قادر خواهند بود:

نرم‌افزارهایی بسازند که نگهداری و به‌روزرسانی آن‌ها بسیار ساده‌تر است.
کدهای خود را به بخش‌های کوچک‌تر تقسیم کنند که هر یک وظیفه مشخصی را بر عهده دارند.
از اصول طراحی مانند SOLID پیروی کنند که باعث ایجاد ساختارهای قوی و انعطاف‌پذیر در نرم‌افزار می‌شود.
با توجه به قابلیت‌های وراثت و چندریختی، تغییرات در نیازهای پروژه به سادگی قابل اعمال خواهد بود.

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

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

معرفی کلاس‌ها و شی‌ها

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

کلاس‌ها (Classes)

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

فیلدها (Fields): متغیرهایی که در داخل یک کلاس قرار دارند و به عنوان داده‌های ذخیره‌شده برای شیء عمل می‌کنند.
خواص (Properties): مشابه فیلدها هستند، اما با استفاده از ویژگی‌های get و set به کنترل دسترسی به داده‌ها و مقداردهی آن‌ها پرداخته می‌شود.
متدها (Methods): توابعی هستند که عملیات مختلفی را روی داده‌های کلاس انجام می‌دهند. آن‌ها می‌توانند ورودی‌هایی دریافت کنند و نتایج را به بیرون برگردانند.

ساختار یک کلاس در سی شارپ

یک کلاس در سی شارپ می‌تواند به این شکل تعریف شود:

public class Person
{
    // فیلدها
    public string Name;
    public int Age;

    // سازنده کلاس برای مقداردهی اولیه
    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }

    // متدها
    public void Introduce()
    {
        Console.WriteLine("سلام، من " + Name + " هستم و " + Age + " سال دارم.");
    }
}

در این مثال، کلاس Person دارای دو فیلد Name و Age است که مشخصات یک فرد را نگهداری می‌کنند. همچنین یک سازنده (Constructor) برای مقداردهی اولیه به این فیلدها و یک متد Introduce() برای معرفی فرد تعریف شده است.

شی‌ها (Objects)

شی‌ها نمونه‌هایی از کلاس‌ها هستند که از روی آن‌ها می‌توان داده‌های خاص و رفتارهای مربوط به یک موجودیت مشخص را ایجاد کرد. وقتی یک شی از یک کلاس ساخته می‌شود، تمام ویژگی‌ها و رفتارهای تعریف‌شده در کلاس به آن شیء منتقل می‌شود.

برای مثال، در کد زیر شیء person1 از کلاس Person ساخته می‌شود:

// ایجاد یک شی از کلاس Person
Person person1 = new Person("علی", 30);
person1.Introduce();  // خروجی: سلام، من علی هستم و 30 سال دارم.

در اینجا، person1 یک نمونه از کلاس Person است و ویژگی‌های خاص خود مثل Name و Age را از این کلاس به ارث می‌برد. با استفاده از شیء person1 می‌توانیم از متد Introduce() استفاده کرده و اطلاعات آن را نمایش دهیم.

ویژگی‌ها و متدها در کلاس‌ها

کلاس‌ها علاوه بر فیلدها، می‌توانند دارای ویژگی‌ها (Properties) و متدها (Methods) نیز باشند.

ویژگی‌ها (Properties): همانطور که گفته شد، ویژگی‌ها به عنوان رابطی بین داده‌های داخلی و خارجی عمل می‌کنند. آن‌ها معمولاً با استفاده از get و set تعریف می‌شوند.
متدها (Methods): متدها توابعی هستند که می‌توانند عملیات مختلفی روی داده‌های کلاس انجام دهند.

مثال پیشرفته‌تر:

public class Car
{
    // فیلدها
    private string model;
    private int year;

    // ویژگی‌ها
    public string Model
    {
        get { return model; }
        set { model = value; }
    }

    public int Year
    {
        get { return year; }
        set { year = value; }
    }

    // متد
    public void StartEngine()
    {
        Console.WriteLine("موتور خودرو " + Model + " شروع به کار کرد.");
    }

    // سازنده
    public Car(string model, int year)
    {
        Model = model;
        Year = year;
    }
}

// ایجاد شی از کلاس Car
Car myCar = new Car("تویوتا", 2022);
myCar.StartEngine();

در این مثال:

ویژگی‌ها Model و Year برای دسترسی به فیلدهای خصوصی model و year استفاده شده‌اند.
متد StartEngine() عملیاتی را روی شیء انجام می‌دهد.
سازنده Car() برای مقداردهی اولیه به ویژگی‌ها استفاده شده است.

تفاوت کلاس و شی:

کلاس یک طرح یا الگو برای ساخت اشیاء است، در حالی که شی نمونه‌ای از یک کلاس است که می‌تواند ویژگی‌ها و متدهای آن کلاس را داشته باشد.
یک کلاس می‌تواند چندین شیء ایجاد کند، اما هر شیء ویژگی‌ها و مقادیر متفاوتی از آن کلاس خواهد داشت.

کلاس‌ها و شی‌ها در شی‌گرایی در سی شارپ به عنوان ابزارهای اصلی برای مدیریت داده‌ها و رفتارها استفاده می‌شوند. کلاس‌ها ساختار کلی و الگویی برای ایجاد اشیاء فراهم می‌کنند و اشیاء نمونه‌های خاصی از آن کلاس‌ها هستند که می‌توانند ویژگی‌ها و رفتارهای منحصر به فرد خود را داشته باشند. این دو مفهوم کمک می‌کنند تا برنامه‌ها به طور منظم، مقیاس‌پذیر و قابل نگهداری باشند.

ویژگی‌ها و متدها در C#

در شی‌گرایی در سی شارپ، دو جزء بسیار مهم وجود دارند که می‌توانند به طور گسترده‌ای در طراحی و پیاده‌سازی کلاس‌ها مورد استفاده قرار گیرند: ویژگی‌ها (Properties) و متدها (Methods). این دو عنصر به برنامه‌نویسان این امکان را می‌دهند که داده‌ها را مدیریت کرده و رفتارهای مربوط به هر کلاس را به طور مؤثر طراحی کنند.

ویژگی‌ها (Properties)

ویژگی‌ها (Properties) در سی شارپ مانند یک رابط عمل می‌کنند که به ما اجازه می‌دهد به فیلدهای خصوصی یک کلاس دسترسی پیدا کنیم. در واقع، ویژگی‌ها به گونه‌ای طراحی شده‌اند که بتوانند داده‌ها را به شکلی امن و کنترل‌شده از طریق متدهای getter و setter مدیریت کنند.

مزایای استفاده از ویژگی‌ها:

کنترل دسترسی: با استفاده از ویژگی‌ها، می‌توانیم از دسترسی مستقیم به فیلدهای داخلی کلاس جلوگیری کرده و تنها از طریق متدهای get و set داده‌ها را تغییر یا بازیابی کنیم.
امنیت داده‌ها: داده‌ها تنها از طریق ویژگی‌ها قابل دسترسی هستند و می‌توان کنترل‌هایی را برای بررسی اعتبار آن‌ها قبل از تغییر ایجاد کرد.
شفافیت: استفاده از ویژگی‌ها به جای فیلدها باعث می‌شود که کد خواناتر و منظم‌تر باشد.

نحوه تعریف ویژگی‌ها:

یک ویژگی در سی شارپ معمولاً از دو بخش تشکیل می‌شود:

Getter: متدی که برای دسترسی به مقدار فیلد استفاده می‌شود.
Setter: متدی که برای تنظیم مقدار فیلد استفاده می‌شود.

مثال عملی برای ویژگی‌ها:

public class Car
{
    // فیلد خصوصی
    private string model;

    // ویژگی با استفاده از Getter و Setter
    public string Model
    {
        get { return model; }
        set { model = value; }
    }
}

در این مثال، ویژگی Model برای دسترسی به فیلد خصوصی model استفاده می‌شود. متد get اجازه می‌دهد که مقدار فیلد model بازیابی شود و متد set اجازه می‌دهد که مقدار آن تغییر کند.

استفاده از ویژگی:

Car myCar = new Car();
myCar.Model = "پراید";  // استفاده از Setter برای مقداردهی
Console.WriteLine(myCar.Model);  // استفاده از Getter برای نمایش مقدار

متدها (Methods)

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

ویژگی‌های متدها:

پارامترها: متدها می‌توانند پارامترهایی دریافت کنند تا عملیات خود را بر اساس آن‌ها انجام دهند.
بازگشت مقدار (Return): برخی متدها مقداری را برمی‌گردانند (مثل متدهایی که نوع بازگشتی دارند)، در حالی که برخی دیگر هیچ مقداری برنمی‌گردانند و فقط یک عملیات را انجام می‌دهند.
دستکاری داده‌ها: متدها می‌توانند بر روی داده‌های کلاس اعمال مختلفی انجام دهند، از جمله محاسبات، تغییرات یا چاپ نتایج.

نحوه تعریف متدها:

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

مثال عملی برای متدها:

public class Car
{
    private string model;

    // ویژگی
    public string Model
    {
        get { return model; }
        set { model = value; }
    }

    // متد
    public void StartEngine()
    {
        Console.WriteLine("موتور خودرو " + Model + " روشن شد.");
    }
}

در این مثال، متد StartEngine عملیاتی را اجرا می‌کند که در اینجا پیام “موتور خودرو روشن شد” را به همراه مدل خودرو چاپ می‌کند.

استفاده از متد:

Car myCar = new Car();
myCar.Model = "پراید";
myCar.StartEngine();  // اجرای متد StartEngine

در اینجا، متد StartEngine برای نمایش پیامی که نشان می‌دهد موتور خودرو روشن شده است، فراخوانی می‌شود.

ترکیب ویژگی‌ها و متدها:

ویژگی‌ها و متدها می‌توانند با یکدیگر ترکیب شوند تا عملکردهای پیچیده‌تری را ایجاد کنند. مثلاً ممکن است متدهایی داشته باشیم که از ویژگی‌ها برای انجام عملیات خاص استفاده کنند و بر اساس آن‌ها تصمیمات جدید بگیرند.

مثال پیشرفته‌تر با ویژگی‌ها و متدها:

public class Car
{
    private string model;
    private int speed;

    // ویژگی‌ها
    public string Model
    {
        get { return model; }
        set { model = value; }
    }

    public int Speed
    {
        get { return speed; }
        set
        {
            if (value < 0)
                Console.WriteLine("سرعت نمی‌تواند منفی باشد.");
            else
                speed = value;
        }
    }

    // متد
    public void Accelerate()
    {
        Speed += 10;
        Console.WriteLine("سرعت خودرو " + Model + " اکنون: " + Speed + " کیلومتر بر ساعت.");
    }
}

در این مثال:

ویژگی Speed به صورت خودکار بررسی می‌کند که سرعت منفی نباشد (با استفاده از set).
متد Accelerate سرعت خودرو را افزایش داده و آن را نمایش می‌دهد.

استفاده از ویژگی‌ها و متدها در عمل:

Car myCar = new Car();
myCar.Model = "تویوتا";
myCar.Speed = 50;
myCar.Accelerate();  // افزایش سرعت خودرو و نمایش آن

ویژگی‌ها (Properties) در سی شارپ به شما این امکان را می‌دهند که دسترسی به فیلدهای داخلی کلاس را کنترل کنید و از getter و setter برای تغییر یا بازیابی مقادیر استفاده کنید.
متدها (Methods) عملکردهای خاصی هستند که می‌توانند داده‌های کلاس را پردازش کرده و عملیات مختلفی انجام دهند.
این دو جزء بسیار مهم در شی‌گرایی در سی شارپ هستند که به برنامه‌نویسان این امکان را می‌دهند که کدهای خوانا، امن و قابل نگهداری بنویسند و به راحتی داده‌ها و رفتارهای برنامه را مدیریت کنند.

نحوه استفاده از سازنده‌ها (Constructors) و دمرهای سازنده در C#

در شی‌گرایی در سی شارپ، سازنده‌ها (Constructors) و دمرهای سازنده (Destructors) از مفاهیم کلیدی هستند که به برنامه‌نویسان کمک می‌کنند تا شیءهای جدید را به درستی مقداردهی کرده و منابع را به‌درستی مدیریت کنند.

1. سازنده‌ها (Constructors)

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

ویژگی‌های سازنده‌ها:

نام سازنده باید دقیقاً مشابه نام کلاس باشد.
سازنده‌ها هیچ‌گونه نوع بازگشتی (return type) ندارند.
سازنده‌ها می‌توانند پیش‌فرض (بدون پارامتر) یا با پارامتر باشند.

انواع سازنده‌ها:

سازنده پیش‌فرض (Default Constructor): این سازنده هیچ پارامتری ندارد و معمولاً برای مقداردهی اولیه به فیلدها استفاده می‌شود.
سازنده با پارامتر (Parameterized Constructor): این سازنده به شما این امکان را می‌دهد که هنگام ایجاد شیء، مقادیری را برای فیلدها وارد کنید.

مثال از سازنده‌ها:

public class Book
{
    public string Title;
    public string Author;

    // سازنده پیش‌فرض
    public Book()
    {
        Title = "عنوان نامشخص";
        Author = "نویسنده نامشخص";
    }

    // سازنده با پارامترها
    public Book(string title, string author)
    {
        Title = title;
        Author = author;
    }

    // متد نمایش اطلاعات کتاب
    public void DisplayInfo()
    {
        Console.WriteLine("عنوان: " + Title + ", نویسنده: " + Author);
    }
}

در این مثال:

سازنده پیش‌فرض Book() مقادیر پیش‌فرض به فیلدهای Title و Author اختصاص می‌دهد.
سازنده با پارامترها Book(string title, string author) به شما این امکان را می‌دهد که هنگام ساخت شیء، اطلاعات خاصی را برای Title و Author وارد کنید.

نحوه استفاده از سازنده‌ها:

Book defaultBook = new Book(); // استفاده از سازنده پیش‌فرض
defaultBook.DisplayInfo(); // خروجی: عنوان: عنوان نامشخص، نویسنده: نویسنده نامشخص

Book specificBook = new Book("سرگذشت یک برنامه‌نویس", "رضا"); // استفاده از سازنده با پارامتر
specificBook.DisplayInfo(); // خروجی: عنوان: سرگذشت یک برنامه‌نویس، نویسنده: رضا

در این کد:

با استفاده از سازنده پیش‌فرض، شیء defaultBook ایجاد می‌شود و مقادیر پیش‌فرض به فیلدها اختصاص داده می‌شود.
با استفاده از سازنده با پارامترها، شیء specificBook ایجاد می‌شود و مقادیر وارد شده برای Title و Author به فیلدها اختصاص می‌یابد.

سازنده‌های متعدد:

یک کلاس می‌تواند چندین سازنده داشته باشد (این ویژگی به نام Overloading شناخته می‌شود) که هر یک پارامترهای مختلفی می‌پذیرند. این قابلیت به شما اجازه می‌دهد که هنگام ایجاد شیء، ورودی‌های مختلفی را بسته به نیاز خود دریافت کنید.

2. دمرهای سازنده (Destructors)

دمرهای سازنده (Destructors) متدهایی هستند که به صورت خودکار و زمانی که یک شیء از حافظه حذف می‌شود، فراخوانی می‌شوند. دمرها معمولاً برای آزادسازی منابعی که شیء ممکن است استفاده کرده باشد (مثل فایل‌ها، اتصالات شبکه و …) استفاده می‌شوند. در سی شارپ، دمرهای سازنده به طور خودکار توسط جمع‌آوری زباله (Garbage Collection) فراخوانی می‌شوند، بنابراین نیازی به فراخوانی دستی آن‌ها نیست.

ویژگی‌های دمرها:

نام دمر باید مشابه نام کلاس باشد.
دمر هیچ پارامتری نمی‌پذیرد.
دمر هیچ‌گونه مقدار برگشتی ندارد.

مثال از دمرها:

public class Book
{
    public string Title;
    public string Author;

    // سازنده
    public Book(string title, string author)
    {
        Title = title;
        Author = author;
    }

    // دمر
    ~Book()
    {
        Console.WriteLine("شیء از حافظه حذف شد.");
    }

    // متد نمایش اطلاعات کتاب
    public void DisplayInfo()
    {
        Console.WriteLine("عنوان: " + Title + ", نویسنده: " + Author);
    }
}

در این مثال، دمر ~Book() زمانی که شیء Book از حافظه حذف می‌شود فراخوانی می‌شود. البته توجه داشته باشید که در سی شارپ، دمرها معمولاً توسط جمع‌آوری زباله (Garbage Collector) مدیریت می‌شوند و نیازی به مدیریت دستی آن‌ها نیست.

استفاده از دمر:

در واقع، چون سی شارپ به طور خودکار از جمع‌آوری زباله استفاده می‌کند، نیازی به فراخوانی دمرها دستی نیست. جمع‌آوری زباله به طور خودکار شیءهایی که دیگر در برنامه به آن‌ها نیاز نیست را حذف می‌کند و در آن زمان دمر اجرا می‌شود.

تفاوت بین سازنده‌ها و دمرها:

سازنده‌ها برای مقداردهی اولیه به شیء هنگام ایجاد آن استفاده می‌شوند.
دمرها برای آزادسازی منابع هنگام حذف شیء از حافظه استفاده می‌شوند.
سازنده‌ها را می‌توان به صورت دستی فراخوانی کرد، اما دمرها تنها توسط سیستم جمع‌آوری زباله فراخوانی می‌شوند.

سازنده‌ها متدهایی ویژه هستند که هنگام ایجاد شیء اجرا می‌شوند و معمولاً برای مقداردهی اولیه به فیلدها استفاده می‌شوند. می‌توانند پیش‌فرض یا با پارامتر باشند.
دمرها متدهایی هستند که هنگام حذف شیء و آزادسازی منابع از حافظه اجرا می‌شوند، اما در سی شارپ به طور خودکار توسط جمع‌آوری زباله مدیریت می‌شوند و به ندرت به فراخوانی دستی نیاز دارند.
این مفاهیم کمک می‌کنند تا به شیوه‌ای کارآمدتر و قابل‌نگهداری‌تر به مدیریت منابع و داده‌های درون شیءها پرداخته و کد خود را بهینه کنید.

مفهوم و کاربرد وراثت در C#

وراثت (Inheritance) یکی از اصول اصلی و کلیدی در شی‌گرایی در سی شارپ است که به کلاس‌ها این امکان را می‌دهد که ویژگی‌ها و متدهای یک کلاس دیگر را به ارث ببرند. این ویژگی باعث استفاده مجدد از کد، کاهش تکرار و ایجاد سلسله مراتب منطقی در برنامه می‌شود. در واقع، وراثت روشی است که در آن یک کلاس جدید می‌تواند از کلاس‌های موجود استفاده کند و خصوصیات و رفتارهای آن‌ها را به ارث برده و در صورت نیاز آن‌ها را گسترش دهد یا تغییر دهد.

1. مفهوم وراثت

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

کلاس پایه (Base Class): کلاسی که ویژگی‌ها و متدهای آن به کلاس‌های مشتق منتقل می‌شود. این کلاس معمولاً شامل ویژگی‌ها و رفتارهای عمومی است که در سایر کلاس‌ها می‌تواند به اشتراک گذاشته شود.
کلاس مشتق (Derived Class): کلاسی که از کلاس پایه وراثت می‌گیرد و می‌تواند ویژگی‌ها و متدهای کلاس پایه را به ارث برده و در صورت نیاز آن‌ها را گسترش دهد یا تغییر دهد.
وراثت به برنامه‌نویسان این امکان را می‌دهد که کدهای خود را سازمان‌دهی کرده و از استفاده مجدد از کد بهره‌مند شوند.

2. نحوه کارکرد وراثت در سی شارپ

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

3. مزایای وراثت

وراثت مزایای زیادی دارد که باعث می‌شود کدها مقیاس‌پذیرتر، قابل نگهداری‌تر و توسعه‌پذیرتر شوند. برخی از مزایای آن عبارتند از:

استفاده مجدد از کد: شما می‌توانید ویژگی‌ها و متدهای کلاس‌های پایه را در کلاس‌های مشتق استفاده کنید و نیازی به نوشتن مجدد آن‌ها ندارید.
ساده‌سازی کد: با استفاده از وراثت، کدها منظم‌تر شده و به جای نوشتن متدها و ویژگی‌ها در چندین کلاس، تنها در یک کلاس پایه نوشته می‌شوند.
گسترش‌پذیری: اگر بخواهید ویژگی‌های جدیدی به کلاس‌های مشتق اضافه کنید، می‌توانید این کار را بدون تغییر در کلاس‌های پایه انجام دهید.

4. وراثت و دسترسی به اعضای کلاس پایه

در سی شارپ، اعضای کلاس پایه می‌توانند با دسترسی‌های مختلف (public، protected، private) دسترسی پیدا کنند. وقتی یک کلاس مشتق از کلاس پایه وراثت می‌گیرد:

اعضای public و protected کلاس پایه در کلاس مشتق قابل دسترسی هستند.
اعضای private در کلاس پایه به طور مستقیم از کلاس مشتق قابل دسترسی نیستند.

مثال عملی از وراثت در سی شارپ:

// کلاس پایه
public class Animal
{
    // متد عمومی که توسط کلاس‌های مشتق قابل دسترسی است
    public void Eat()
    {
        Console.WriteLine("جانور در حال خوردن است.");
    }
}

// کلاس مشتق که از کلاس Animal وراثت می‌گیرد
public class Dog : Animal
{
    // متد خاص کلاس Dog
    public void Bark()
    {
        Console.WriteLine("سگ پارس می‌کند.");
    }
}

// استفاده از وراثت
Dog myDog = new Dog();
myDog.Eat();   // استفاده از متد وراثت شده از Animal
myDog.Bark();  // استفاده از متد خاص کلاس Dog

توضیحات کد:

در این مثال، کلاس Animal یک متد به نام Eat دارد که رفتار عمومی مربوط به خوردن را مشخص می‌کند.
کلاس Dog از کلاس Animal وراثت می‌گیرد. بنابراین، کلاس Dog به متد Eat دسترسی دارد، علاوه بر این، متد خاص خود به نام Bark را تعریف می‌کند که رفتار پارس کردن سگ را نشان می‌دهد.
هنگام استفاده از شیء myDog که از کلاس Dog ساخته شده، می‌توان هم از متد وراثت شده Eat استفاده کرد و هم از متد اختصاصی Bark.

5. مفهوم Overriding و Overloading در وراثت

Overriding: این امکان را به کلاس‌های مشتق می‌دهد تا متدهای کلاس پایه را بازنویسی کرده و رفتار آن‌ها را تغییر دهند.

برای انجام این کار، باید از کلمه کلیدی virtual در کلاس پایه و override در کلاس مشتق استفاده کرد.
مثال:

// کلاس پایه
public class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("صدای جانور");
    }
}

// کلاس مشتق
public class Dog : Animal
{
    // بازنویسی متد MakeSound
    public override void MakeSound()
    {
        Console.WriteLine("پارس!");
    }
}

Dog dog = new Dog();
dog.MakeSound();  // خروجی: پارس!

Overloading: به این معنی است که می‌توانید چندین متد با نام مشابه در یک کلاس تعریف کنید، اما هر کدام پارامترهای متفاوتی می‌پذیرند.

مثال:

public class Calculator
{
    // متد جمع دو عدد
    public int Add(int a, int b)
    {
        return a + b;
    }

    // متد جمع سه عدد
    public int Add(int a, int b, int c)
    {
        return a + b + c;
    }
}

Calculator calc = new Calculator();
Console.WriteLine(calc.Add(2, 3));    // خروجی: 5
Console.WriteLine(calc.Add(2, 3, 4)); // خروجی: 9

6. وراثت چندگانه در C#

در سی شارپ، برخلاف زبان‌های دیگر مانند C++، وراثت چندگانه (وراثت از چندین کلاس به طور همزمان) پشتیبانی نمی‌شود. اما می‌توان از رابط‌ها (Interfaces) برای دستیابی به رفتار مشابه استفاده کرد. در واقع، یک کلاس می‌تواند از چندین رابط وراثت بگیرد.  وراثت در شی‌گرایی در سی شارپ ابزار بسیار قدرتمندی است که امکان استفاده مجدد از کد را فراهم می‌کند و باعث می‌شود که ساختار برنامه منظم‌تر و مقیاس‌پذیرتر شود. با استفاده از وراثت، می‌توان یک سلسله مراتب منطقی از کلاس‌ها ایجاد کرده و رفتارهای عمومی را در کلاس‌های پایه تعریف کرده و در کلاس‌های مشتق تغییرات و ویژگی‌های خاص را اضافه کرد.

استفاده از چندریختی (Polymorphism) در C#

چندریختی (Polymorphism) یکی از اصول پایه‌ای در شی‌گرایی است که در سی شارپ به شما این امکان را می‌دهد که یک متد واحد می‌تواند در کلاس‌های مختلف به شیوه‌های متفاوت اجرا شود. این ویژگی به شما اجازه می‌دهد که کدهای انعطاف‌پذیر و قابل توسعه‌ای بنویسید که به راحتی می‌توان آن‌ها را تغییر داده و گسترش داد.

چندریختی در C# به دو شکل اصلی پیاده‌سازی می‌شود: Overriding و Overloading. هر یک از این دو نوع چندریختی کاربردها و ویژگی‌های خاص خود را دارند.

1. Overriding در C# (بازنویسی متدها)

Overriding به شما این امکان را می‌دهد که متدهای یک کلاس پایه را در کلاس‌های مشتق بازنویسی کنید تا رفتار آن‌ها را تغییر دهید. این ویژگی به شما این امکان را می‌دهد که یک متد در کلاس پایه به صورت عمومی تعریف شود و در کلاس‌های مشتق، پیاده‌سازی خاصی برای آن بنویسید. این تغییر رفتار معمولاً به منظور تغییر یا گسترش عملکرد متد کلاس پایه در کلاس‌های مشتق صورت می‌گیرد.

ویژگی‌های مهم Overriding:

برای استفاده از Overriding، باید در کلاس پایه از کلمه کلیدی virtual استفاده کنید تا نشان‌دهنده این باشد که متد قابل بازنویسی است.
در کلاس مشتق، از کلمه کلیدی override استفاده می‌کنید تا نشان دهید که متد کلاس پایه را بازنویسی می‌کنید.

مزایای Overriding:

به شما امکان می‌دهد که از یک متد با رفتارهای مختلف در کلاس‌های مختلف استفاده کنید.
انعطاف‌پذیری بالایی برای تغییر و گسترش رفتارهای یک کلاس فراهم می‌کند.

مثال از Overriding:

// کلاس پایه
public class Animal
{
    public virtual void Speak()
    {
        Console.WriteLine("حیوان صدایی تولید می‌کند.");
    }
}

// کلاس مشتق
public class Dog : Animal
{
    public override void Speak()
    {
        Console.WriteLine("سگ پارس می‌کند.");
    }
}

// کلاس مشتق
public class Cat : Animal
{
    public override void Speak()
    {
        Console.WriteLine("گربه میو می‌کند.");
    }
}

Animal animal1 = new Dog();
Animal animal2 = new Cat();

animal1.Speak(); // خروجی: سگ پارس می‌کند.
animal2.Speak(); // خروجی: گربه میو می‌کند.

در این مثال:

متد Speak در کلاس پایه Animal به صورت virtual تعریف شده است، به این معنی که این متد می‌تواند در کلاس‌های مشتق بازنویسی شود.
سپس کلاس‌های Dog و Cat متد Speak را بازنویسی کرده‌اند تا صدای خاص خود را تولید کنند.
وقتی شیء از نوع Animal به متد Speak فراخوانی می‌شود، سی شارپ به طور خودکار متد مناسب را براساس نوع واقعی شیء (نه نوع اعلام شده) فراخوانی می‌کند. به همین دلیل، animal1.Speak() در ابتدا خروجی “سگ پارس می‌کند.” و در دومی “گربه میو می‌کند.” را نمایش می‌دهد.

2. Overloading در C# (بیش از یک متد با نام مشابه)

Overloading به شما این امکان را می‌دهد که چندین متد با همان نام اما با پارامترهای متفاوت در یک کلاس تعریف کنید. در این روش، شما می‌توانید به راحتی متدهای مشابه را برای انجام عملیات مختلف با تعداد متفاوتی از پارامترها استفاده کنید. این یک روش بسیار مفید برای بهینه‌سازی کد است زیرا نیازی به تعریف چندین متد با نام‌های متفاوت نخواهید داشت.

ویژگی‌های مهم Overloading:

در Overloading، متدهای مختلف با نام مشابه ولی با تعداد و نوع پارامترهای متفاوتی تعریف می‌شوند.
سی شارپ به صورت خودکار مناسب‌ترین متد را با توجه به تعداد و نوع پارامترهای ارسال‌شده انتخاب می‌کند.
برخلاف Overriding که در کلاس‌های مشتق استفاده می‌شود، Overloading در داخل یک کلاس انجام می‌شود و به کلاس‌های مشتق ارتباطی ندارد.

مزایای Overloading:

به راحتی می‌توان متدهایی با پارامترهای متفاوت و نیازهای مختلف ایجاد کرد.
باعث خوانایی و سازمان‌دهی بهتر کد می‌شود.

مثال از Overloading:

public class Calculator
{
    // متد جمع دو عدد
    public int Add(int a, int b)
    {
        return a + b;
    }

    // متد جمع سه عدد
    public int Add(int a, int b, int c)
    {
        return a + b + c;
    }

    // متد جمع چهار عدد
    public int Add(int a, int b, int c, int d)
    {
        return a + b + c + d;
    }
}

Calculator calc = new Calculator();
Console.WriteLine(calc.Add(2, 3));        // خروجی: 5
Console.WriteLine(calc.Add(2, 3, 4));     // خروجی: 9
Console.WriteLine(calc.Add(2, 3, 4, 5));  // خروجی: 14

در این مثال:

ما از Overloading برای تعریف چندین متد با نام Add استفاده کرده‌ایم که می‌توانند تعداد متفاوتی از پارامترها را بپذیرند.
به این ترتیب، با یک نام متد (Add) می‌توانیم عملیات جمع را برای دو، سه یا چهار عدد انجام دهیم، بدون اینکه به نام‌های مختلفی برای هرکدام نیاز داشته باشیم.

3. ترکیب Overriding و Overloading برای پیاده‌سازی چندریختی

با استفاده از Overriding و Overloading می‌توانید چندریختی را به شیوه‌های مختلف و قدرتمندتری در برنامه‌های خود پیاده‌سازی کنید.

مثال ترکیبی:

public class Shape
{
    public virtual void Draw()
    {
        Console.WriteLine("رسم شکل کلی");
    }
}

public class Circle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("رسم دایره");
    }

    public void Draw(int radius)
    {
        Console.WriteLine("رسم دایره با شعاع " + radius);
    }
}

Shape myShape = new Circle();
myShape.Draw();  // خروجی: رسم دایره

Circle myCircle = new Circle();
myCircle.Draw(5);  // خروجی: رسم دایره با شعاع 5

در این مثال:

متد Draw در کلاس Shape به صورت virtual تعریف شده است و در کلاس Circle بازنویسی شده است.
در کلاس Circle علاوه بر Overriding، متد دیگری به نام Draw با پارامترهای مختلف (برای مشخص کردن شعاع دایره) نیز اضافه شده است که این یک نمونه از Overloading است.

4. کاربردهای چندریختی

چندریختی در طراحی نرم‌افزار بسیار مفید است و در موارد زیر کاربرد دارد:

طراحی سیستم‌های انعطاف‌پذیر: می‌توانید متدهای مشابه با رفتارهای متفاوت برای کلاس‌های مختلف داشته باشید.
استفاده مجدد از کد: با استفاده از بازنویسی متدهای پایه، می‌توانید کدهای تکراری را کاهش داده و از کدهای موجود بهره ببرید.
سهولت در نگهداری و گسترش برنامه: با داشتن رفتارهای مختلف در کلاس‌های مختلف، می‌توانید تغییرات را به راحتی اعمال کنید بدون اینکه نیاز به تغییر در ساختارهای دیگر داشته باشید.

چندریختی در C# از طریق Overriding و Overloading به شما این امکان را می‌دهد که متدهای مشابه را با رفتارهای مختلف در کلاس‌های مختلف داشته باشید و همین امر باعث می‌شود که برنامه‌های شما انعطاف‌پذیرتر، مقیاس‌پذیرتر و قابل نگهداری‌تر باشند. این ویژگی در طراحی نرم‌افزار بسیار مفید است و از طریق آن می‌توانید سیستم‌هایی پیچیده‌تر و بهینه‌تر ایجاد کنید.

مفهوم انتزاع (Abstraction) و نحوه پیاده‌سازی آن در C#

انتزاع (Abstraction) یکی از اصول کلیدی در شی‌گرایی است که هدف آن ساده‌سازی پیچیدگی‌ها و متمرکز کردن توجه بر ویژگی‌های اصلی یک شیء است. در واقع، انتزاع یعنی تنها نمایش جزئیات مهم و ضروری و پنهان کردن جزئیات غیرضروری و پیچیده که به کاربر نهایی یا دیگر بخش‌های سیستم نیازی به دانستن آن‌ها نیست. این مفهوم در زبان‌های برنامه‌نویسی شی‌گرا مانند C# به طور گسترده مورد استفاده قرار می‌گیرد.

در C#، انتزاع معمولاً از طریق کلاس‌های انتزاعی (Abstract Classes) و متدهای انتزاعی (Abstract Methods) پیاده‌سازی می‌شود. این دو ویژگی به برنامه‌نویس این امکان را می‌دهند که تنها پیاده‌سازی‌های کلی یک شیء را تعریف کرده و جزئیات پیاده‌سازی را به کلاس‌های مشتق واگذار کند.

1. کلاس انتزاعی (Abstract Class)

کلاس انتزاعی در C# یک کلاسی است که نمی‌توان از آن شیء مستقیم ساخت. این کلاس معمولاً شامل متدها و ویژگی‌هایی است که رفتار کلی یک شیء را تعریف می‌کنند، اما ممکن است پیاده‌سازی جزئیات آن‌ها به عهده کلاس‌های مشتق باشد. کلاس انتزاعی می‌تواند شامل متدهای انتزاعی (Abstract Methods) باشد که در این صورت کلاس‌های مشتق باید پیاده‌سازی آن‌ها را انجام دهند.

ویژگی‌های کلاس انتزاعی:

کلاس‌های انتزاعی نمی‌توانند نمونه (شیء) ایجاد کنند. این کلاس‌ها تنها برای تعریف رفتارهای عمومی و پایه‌ای برای کلاس‌های مشتق استفاده می‌شوند.
می‌توانند متدهایی با پیاده‌سازی یا بدون پیاده‌سازی (انتزاعی) داشته باشند.
کلاس‌های مشتق از کلاس‌های انتزاعی می‌توانند متدهای انتزاعی را پیاده‌سازی کنند.
مزایای استفاده از کلاس‌های انتزاعی:
کاهش پیچیدگی کد و تمرکز بر ویژگی‌های اصلی.
تعیین یک مدل کلی برای رفتارهای آینده.
امکان گسترش راحت‌تر کدها با اضافه کردن ویژگی‌ها به کلاس‌های مشتق.

2. متد انتزاعی (Abstract Method)

یک متد انتزاعی در C# یک متدی است که در کلاس انتزاعی تعریف می‌شود اما پیاده‌سازی ندارد. این متد باید توسط هر کلاسی که از کلاس انتزاعی مشتق می‌شود، پیاده‌سازی شود. به عبارت دیگر، این متد تنها امضای خود را دارد و پیاده‌سازی واقعی آن در کلاس‌های مشتق انجام می‌شود.

ویژگی‌های متد انتزاعی:

متدهای انتزاعی فقط امضای خود را دارند و هیچ کد اجرایی در آن‌ها وجود ندارد.
متدهای انتزاعی باید در کلاس‌های مشتق پیاده‌سازی شوند و نمی‌توانند در کلاس انتزاعی پیاده‌سازی شوند.
متدهای انتزاعی معمولاً برای مشخص کردن عملیات کلی و اصلی یک شیء استفاده می‌شوند که باید به صورت خاص در هر کلاس مشتق پیاده‌سازی شوند.

3. پیاده‌سازی انتزاع در C#

برای پیاده‌سازی انتزاع در C#، از کلمه کلیدی abstract برای تعریف کلاس‌های انتزاعی و متدهای انتزاعی استفاده می‌کنیم. در اینجا مثالی از نحوه استفاده از این ویژگی‌ها آورده شده است.

مثال عملی:

// کلاس انتزاعی
public abstract class Employee
{
    public string Name;

    // متد انتزاعی
    public abstract void Work();
}

// کلاس مشتق
public class Developer : Employee
{
    public override void Work()
    {
        Console.WriteLine(Name + " در حال کدنویسی است.");
    }
}

// کلاس مشتق
public class Manager : Employee
{
    public override void Work()
    {
        Console.WriteLine(Name + " در حال مدیریت پروژه است.");
    }
}

class Program
{
    static void Main()
    {
        Developer dev = new Developer();
        dev.Name = "سارا";
        dev.Work();  // خروجی: سارا در حال کدنویسی است.

        Manager mgr = new Manager();
        mgr.Name = "محمود";
        mgr.Work();  // خروجی: محمود در حال مدیریت پروژه است.
    }
}

توضیحات:
در این مثال، کلاس Employee یک کلاس انتزاعی است که شامل یک متد انتزاعی به نام Work است. این متد هیچ پیاده‌سازی‌ای در کلاس Employee ندارد و باید توسط کلاس‌های مشتق پیاده‌سازی شود.
دو کلاس Developer و Manager از کلاس Employee مشتق شده‌اند و هرکدام متد Work را به شیوه‌ای خاص پیاده‌سازی کرده‌اند.
در بخش Main، هرکدام از شیءهای dev و mgr که از کلاس‌های مشتق Developer و Manager ساخته شده‌اند، متد Work را فراخوانی می‌کنند که خروجی خاص خود را تولید می‌کند.

 کاربردهای انتزاع در C#

انتزاع در C# به شما این امکان را می‌دهد که:

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

مزایای استفاده از انتزاع در C#

کاهش پیچیدگی: انتزاع کمک می‌کند که پیچیدگی‌ها از جزئیات داخلی مخفی بمانند و تنها ویژگی‌های مهم برای کاربر نهایی در دسترس باشد.
افزایش انعطاف‌پذیری و مقیاس‌پذیری: از آنجایی که جزئیات پیاده‌سازی به کلاس‌های مشتق واگذار می‌شود، می‌توانید به راحتی ویژگی‌های جدیدی به سیستم اضافه کنید بدون اینکه نیاز به تغییرات بزرگ در کدهای موجود باشد.
توسعه‌پذیری آسان‌تر: با استفاده از کلاس‌های انتزاعی و متدهای انتزاعی، توسعه سیستم‌ها به راحتی انجام می‌شود چرا که پیاده‌سازی‌های جدید تنها باید متدهای انتزاعی را پیاده‌سازی کنند.

انتزاع در C# یک ابزار قدرتمند برای ساده‌سازی طراحی سیستم‌های پیچیده است. با استفاده از کلاس‌های انتزاعی و متدهای انتزاعی، می‌توانید جزئیات غیرضروری را پنهان کرده و تمرکز خود را بر روی ویژگی‌ها و رفتارهای اصلی سیستم بگذارید. این کار باعث می‌شود که کدهای شما قابل فهم‌تر، قابل نگهداری‌تر و قابل توسعه‌تر باشند.

رابط‌ها (Interfaces) و پیاده‌سازی آن‌ها در C#

رابط‌ها (Interfaces) یکی از مفاهیم کلیدی در شی‌گرایی در سی شارپ هستند که به شما این امکان را می‌دهند که مجموعه‌ای از متدها و خواص را بدون پیاده‌سازی مشخص تعریف کنید. سپس کلاس‌ها می‌توانند این رابط‌ها را پیاده‌سازی کرده و رفتار مورد نظر خود را برای این متدها و خواص تعیین کنند. رابط‌ها باعث می‌شوند که کد شما انعطاف‌پذیرتر، مقیاس‌پذیرتر و قابل تست‌تر باشد.

1. رابط (Interface) چیست؟

در سی شارپ، رابط یک نوع خاص از کلاس است که نمی‌تواند شیء‌ای از آن ساخته شود. رابط‌ها تنها شامل امضاهای متدها و خواص هستند و هیچ پیاده‌سازی‌ای از این متدها و خواص ندارند. رابط‌ها در واقع یک قرارداد هستند که به یک کلاس می‌گویند که باید متدهای خاصی را پیاده‌سازی کند.

ویژگی‌های رابط‌ها:

رابط‌ها تنها شامل امضاهای متدها و خواص هستند: یعنی فقط نام متدها، پارامترها و نوع بازگشتی مشخص است.
رابط‌ها نمی‌توانند شامل پیاده‌سازی متدها باشند: پیاده‌سازی واقعی متدها باید در کلاس‌های مشتق از رابط انجام شود.
یک کلاس می‌تواند چندین رابط را پیاده‌سازی کند: برخلاف وراثت کلاس‌ها که تنها یک کلاس پایه می‌تواند وجود داشته باشد، کلاس‌ها در سی شارپ می‌توانند چندین رابط را پیاده‌سازی کنند (وراثت چندگانه رابط‌ها).
رابط‌ها نمی‌توانند داده‌ها یا فیلدها داشته باشند: رابط‌ها فقط می‌توانند امضاهای متدها و خواص را داشته باشند.

کاربرد رابط‌ها:

تعریف قراردادها: رابط‌ها به شما این امکان را می‌دهند که یک قرارداد برای متدهای مورد نیاز تعریف کنید که کلاس‌های مختلف باید آن را پیاده‌سازی کنند.
گسترش‌پذیری و انعطاف‌پذیری: رابط‌ها امکان گسترش و اصلاح سیستم را بدون ایجاد تغییرات بزرگ در سایر قسمت‌های کد فراهم می‌آورند.

2. پیاده‌سازی رابط‌ها

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

ویژگی‌های پیاده‌سازی رابط‌ها:

کلاس باید تمامی متدها و خواص رابط را پیاده‌سازی کند.
کلاس‌ها می‌توانند بیش از یک رابط را پیاده‌سازی کنند.
متدهای پیاده‌سازی شده در کلاس باید همان امضاهای رابط را داشته باشند.

مثال از رابط‌ها و پیاده‌سازی آن‌ها:

در اینجا مثالی از نحوه تعریف یک رابط و پیاده‌سازی آن در یک کلاس آورده شده است.

// تعریف رابط
public interface ILogger
{
    void Log(string message);
}

// پیاده‌سازی رابط در کلاس FileLogger
public class FileLogger : ILogger
{
    public void Log(string message)
    {
        Console.WriteLine("لاگ در فایل: " + message);
        // در یک سناریوی واقعی، پیام به فایل نوشته می‌شود.
    }
}

// پیاده‌سازی رابط در کلاس DatabaseLogger
public class DatabaseLogger : ILogger
{
    public void Log(string message)
    {
        Console.WriteLine("لاگ در پایگاه داده: " + message);
        // در یک سناریوی واقعی، پیام به پایگاه داده ذخیره می‌شود.
    }
}

// استفاده از رابط
ILogger logger1 = new FileLogger();
ILogger logger2 = new DatabaseLogger();

logger1.Log("این یک پیام لاگ است.");
logger2.Log("این پیام به پایگاه داده لاگ می‌شود.");

توضیحات:

در این مثال، رابط ILogger یک متد Log تعریف کرده است که پیام‌هایی را به عنوان ورودی می‌گیرد و آن‌ها را ثبت می‌کند.
کلاس FileLogger این رابط را پیاده‌سازی کرده است و متد Log را برای ثبت پیام‌ها به صورت “لاگ در فایل” تعریف می‌کند.
کلاس DatabaseLogger نیز همین رابط را پیاده‌سازی کرده است و متد Log را برای ثبت پیام‌ها در پایگاه داده تعریف می‌کند.
در قسمت Main، از هر دو کلاس به عنوان نوع ILogger استفاده شده است که نشان‌دهنده این است که متد Log در هر کلاس به صورت مستقل از نوع کلاس پیاده‌سازی شده است.

3. چند رابط در یک کلاس

یک کلاس می‌تواند چندین رابط را پیاده‌سازی کند، که این ویژگی در سی شارپ به شما این امکان را می‌دهد که رفتارهای مختلف را از طریق رابط‌ها ترکیب کنید. این یکی از ویژگی‌های مفید وراثت چندگانه در سی شارپ است.

مثال از چند رابط در یک کلاس:

public interface ILogger
{
    void Log(string message);
}

public interface INotifier
{
    void Notify(string message);
}

public class NotificationLogger : ILogger, INotifier
{
    public void Log(string message)
    {
        Console.WriteLine("لاگ: " + message);
    }

    public void Notify(string message)
    {
        Console.WriteLine("اعلامیه: " + message);
    }
}

class Program
{
    static void Main()
    {
        NotificationLogger notificationLogger = new NotificationLogger();
        notificationLogger.Log("این یک پیام لاگ است.");
        notificationLogger.Notify("این یک پیام اعلامیه است.");
    }
}

توضیحات:
در این مثال، کلاس NotificationLogger هر دو رابط ILogger و INotifier را پیاده‌سازی می‌کند.
متدهای Log و Notify در کلاس NotificationLogger پیاده‌سازی شده‌اند و به ترتیب برای ثبت پیام‌ها و ارسال اعلان‌ها استفاده می‌شوند.

4. مزایای استفاده از رابط‌ها

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

رابط‌ها در C# ابزار بسیار قدرتمندی برای طراحی سیستم‌های شی‌گرا هستند که به شما این امکان را می‌دهند که پیاده‌سازی‌های خود را از رفتارها جدا کرده و کدهای انعطاف‌پذیرتر، مقیاس‌پذیرتر و قابل نگهداری‌تری بنویسید. از طریق رابط‌ها می‌توانید قراردادهایی برای متدها و خواص تعریف کنید که کلاس‌ها باید آن‌ها را پیاده‌سازی کنند و همین امر باعث می‌شود که سیستم‌های شما به راحتی گسترش‌پذیر و قابل تغییر باشند.

نتیجه‌گیری

در این مقاله به بررسی مفاهیم مختلف شی‌گرایی در سی شارپ پرداخته شد که شامل کلاس‌ها، اشیاء، سازنده‌ها، وراثت، چندریختی، انتزاع و رابط‌ها بود. با استفاده از این مفاهیم، می‌توان سیستم‌های پیچیده را به صورت ماژولار و قابل نگهداری طراحی کرد. شی‌گرایی در سی شارپ از طریق ویژگی‌هایی همچون وراثت و چندریختی، انعطاف‌پذیری بالایی به کدهای شما می‌دهد و این امکان را فراهم می‌آورد که کدهای تکراری را کاهش دهید و از پیاده‌سازی‌های مختلف در کلاس‌ها استفاده کنید.

در نهایت، مفاهیم انتزاع و رابط‌ها در سی شارپ به شما این امکان را می‌دهند که سیستم‌هایی با مقیاس‌پذیری و گسترش‌پذیری بالا بسازید. استفاده صحیح از این اصول می‌تواند کد شما را سازمان‌دهی کرده و آن را برای نگهداری و توسعه در آینده آماده کند. شی‌گرایی در سی شارپ به عنوان یک ابزار قدرتمند، شما را قادر می‌سازد که برنامه‌های قوی و کارآمد ایجاد کنید که هم‌زمان قابل فهم و انعطاف‌پذیر باشند.

آموزش شی‌گرایی در سی شارپ

دیدگاه های شما

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *