مقدمه

به فصل پنجم و دنیای شگفت‌انگیز برنامه‌نویسی شیءگرا (Object-Oriented Programming - OOP) خوش آمدید! تا به اینجا با ساختارهای پایه‌ای زبان C# آشنا شده‌ایم. اکنون زمان آن رسیده که یاد بگیریم چگونه با استفاده از کلاس‌ها، مفاهیم دنیای واقعی را در قالب کدهای ساختاریافته و قابل مدیریت مدل‌سازی کنیم. کلاس (Class) مهم‌ترین و بنیادی‌ترین مفهوم در OOP و قلب تپنده‌ی زبان C# است. یک کلاس در واقع یک نقشه یا بلوپرینت برای ساختن اشیاء (Objects) است. در این درس، با نحوه‌ی تعریف کلاس، ایجاد اشیاء از روی آن و نقش حیاتی سازنده‌ها (Constructors) در مقداردهی اولیه این اشیاء آشنا خواهیم شد.

تعریف یک کلاس

یک کلاس، داده‌ها (اطلاعات) و رفتارها (عملیات) مرتبط با یک مفهوم را در یک واحد منسجم به نام شیء (Object) کپسوله می‌کند. برای تعریف یک کلاس از کلمه‌ی کلیدی class استفاده می‌کنیم. بیایید یک مفهوم ساده مانند "اتومبیل" را به عنوان یک کلاس مدل‌سازی کنیم.

فیلدها و متدها: داده و رفتار

یک کلاس معمولاً از دو جزء اصلی تشکیل می‌شود:

  • فیلدها (Fields): متغیرهایی هستند که درون کلاس تعریف می‌شوند و وضعیت (state) یا داده‌های یک شیء را نگهداری می‌کنند. برای مثال، مدل، رنگ و سال ساخت یک اتومبیل فیلدهای آن هستند.
  • متدها (Methods): توابعی هستند که درون کلاس تعریف می‌شوند و رفتار (behavior) یک شیء را مشخص می‌کنند. برای مثال، روشن کردن موتور یا شتاب گرفتن، متدهای کلاس اتومبیل هستند.
Copy Icon Program.cs
public class Car
{
    // Fields to store the car's state
    public string Model;
    public string Color;
    public int Year;

    // A method to describe the car's behavior
    public void StartEngine()
    {
        Console.WriteLine($"The {Model} engine starts. Vroom!");
    }
}

در کد بالا، یک کلاس به نام Car تعریف کرده‌ایم. این کلاس سه فیلد عمومی (Model، Color و Year) برای ذخیره‌ی اطلاعات اتومبیل و یک متد عمومی (StartEngine) برای تعریف یکی از رفتارهای آن دارد. در حال حاضر فیلدها را public تعریف کرده‌ایم، اما در درس‌های آینده خواهیم دید که بهترین روش، خصوصی (private) کردن فیلدها و کنترل دسترسی به آن‌هاست (مفهوم Encapsulation).

ایجاد اشیاء (نمونه‌سازی)

کلاس به تنهایی یک نقشه است و تا زمانی که از روی آن یک شیء واقعی نسازیم، کاربردی ندارد. فرآیند ساختن یک شیء از روی یک کلاس را نمونه‌سازی (Instantiation) می‌نامند. برای این کار از کلمه‌ی کلیدی new استفاده می‌کنیم.

Copy Icon Program.cs
// Create an instance (an object) of the Car class
Car myCar = new Car();

// Assign values to the object's fields using the dot operator
myCar.Model = "Tesla Model S";
myCar.Color = "Red";
myCar.Year = 2024;

Console.WriteLine($"My car is a {myCar.Color} {myCar.Year} {myCar.Model}.");

// Call the object's method
myCar.StartEngine();

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

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

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

نقش سازنده‌ها

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

سازنده‌ی پیش‌فرض و سفارشی

اگر شما هیچ سازنده‌ای برای کلاس خود تعریف نکنید، کامپایلر C# یک سازنده‌ی عمومی و بدون پارامتر به نام سازنده‌ی پیش‌فرض (Default Constructor) برای شما ایجاد می‌کند. این سازنده فیلدهای کلاس را با مقادیر پیش‌فرضشان (صفر برای اعداد، null برای ارجاعی‌ها و false برای bool) مقداردهی می‌کند. این همان سازنده‌ای بود که در مثال قبلی برای new Car() فراخوانی شد.

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

Copy Icon Program.cs
public class Car
{
    public string Model;
    public int Year;

    // A custom constructor
    public Car(string model, int year)
    {
        Model = model;
        Year = year;
    }
    
    // ... other methods
}

// Now we MUST provide arguments when creating an object
Car myCar = new Car("Ford Mustang", 1969);
Console.WriteLine($"Created a {myCar.Year} {myCar.Model}.");

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

کلمه‌ی کلیدی this

کلمه‌ی کلیدی this یک ارجاع به نمونه‌ی فعلی کلاس است. این کلمه کلیدی کاربردهای مختلفی دارد، اما رایج‌ترین کاربرد آن برای رفع ابهام بین نام پارامترهای یک متد (به‌ویژه سازنده) و نام فیلدهای کلاس است.

Copy Icon Program.cs
public class Person
{
    // Private fields - A better practice
    private string name;
    private int age;

    public Person(string name, int age)
    {
        // 'this.name' refers to the field of the class.
        // 'name' refers to the parameter of the constructor.
        this.name = name;
        this.age = age;
    }

    public void Introduce()
    {
        Console.WriteLine($"Hi, I am {this.name} and I am {this.age} years old.");
    }
}

در سازنده‌ی کلاس Person، نام پارامترها (name و age) با نام فیلدهای کلاس یکسان است. برای اینکه به کامپایلر بگوییم منظور ما فیلد کلاس است، از this.name و this.age استفاده می‌کنیم. این یک قرارداد رایج و بسیار خوانا در برنامه‌نویسی C# است و به ما اجازه می‌دهد از نام‌های توصیفی و یکسان برای پارامترها و فیلدها استفاده کنیم.