ویژگی‌ها (Properties) در کلاس‌ها در زبان سی شارپ

09 فروردین 1398
درسنامه درس 13 از سری آموزش سی شارپ (C#)
csharp-properties

با مطالعه‌ی فصل گذشته اطلاعات مفیدی در ارتباط با مفهوم Polymorphism بدست آوردید و نحوه‌ی کار کردن با انواع روش‌های اعمال محدودیت روی یک کلاس، متد را آموختید. در این فصل می‌خواهیم درباره مفهومی بسیار مهم تحت عنوان ویژگی‌ها یا Properties‌ها در زبان برنامه‌نویسی #C صحبت کنیم. با ما همراه باشید.

مقدمه

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

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

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

using System;

public class Customer
{
    private int m_id = -1;

    public int GetID()
    {
        return m_id;
    }

    public void SetID(int id)
    {
        m_id = id;
    }

    private string m_name = string.Empty;

    public string GetName()
    {
        return m_name;
    }

    public void SetName(string name)
    {
        m_name = name;
    }
}

public class CustomerManagerWithAccessorMethods
{
    public static void Main()
    {
        Customer cust = new Customer();

        cust.SetID(1);
        cust.SetName("Amelio Rosales");

        Console.WriteLine(
            "ID: {0}, Name: {1}",
            cust.GetID(),
            cust.GetName());

        Console.ReadKey();
    }
}

همانطور که در این مثال مشاهده می‌کنید برای فیلد خصوصی m_id‌ دو متد به نام‌های GetID و SetID ایجاد کرده‌ایم. همچنین اینکار را برای فیلد m_name انجام داده‌ایم. سپس در تابع اصلی Main یک شیء از کلاس Customer ایجاد کرده و مقادیر ID و Name را برای آن مشخص کرده‌ایم. در نهایت با استفاده از متد Get مقدار آنها را دریافت کرده‌ایم.

این فرم نوشتاری فلسفه‌ی نوشتن یک ویژگی یا Property است. در ادامه یک Property را با فرم استاندار می‌نویسیم:

using System;

public class Customer
{
    private int m_id = -1;

    public int ID
    {
        get
        {
            return m_id;
        }
        set
        {
            m_id = value;
        }
    }

    private string m_name = string.Empty;

    public string Name
    {
        get
        {
            return m_name;
        }
        set
        {
            m_name = value;
        }
    }
}

public class CustomerManagerWithProperties
{
    public static void Main()
    {
        Customer cust = new Customer();

        cust.ID = 1;
        cust.Name = "Amelio Rosales";

	Console.WriteLine(
            "ID: {0}, Name: {1}",
            cust.ID,
            cust.Name);

        Console.ReadKey();
    }
}

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

ساخت ویژگی‌های Read-Only

می‌توان یک ویژگی را به‌گونه‌ای ایجاد کرد که تنها اطلاعاتی از روی آن خوانده شود و چیزی به عنوان تنظیم کننده یا setter نداشته باشد. به مثال زیر دقت کنید:

using System;

public class Customer
{
    private int m_id = -1;
    private string m_name = string.Empty;

    public Customer(int id, string name)
    {
        m_id = id;
        m_name = name;
    }

    public int ID
    {
        get
        {
            return m_id;
        }
    }

    public string Name
    {
        get
        {
            return m_name;
        }
    }
}

public class ReadOnlyCustomerManager
{
    public static void Main()
    {
        Customer cust = new Customer(1, "Amelio Rosales");

        Console.WriteLine(
            "ID: {0}, Name: {1}",
            cust.ID,
            cust.Name);

        Console.ReadKey();
    }
}

ابتدا یک کلاس به نام ReadOnlyCustomerManager ایجاد و سپس دو فیلد به نام m_id و m_name را تعریف و مقداردهی کرده‌ایم. در مرحله بعدی سازنده کلاس را نوشته و برای آن آرگومانی درنظر گرفته‌ایم. سپس دو ویژگی به نام‌های ID و Name از نوع Int و String تعریف کرده و در نهایت درون متد اصلی Main آنها را فراخوانی کرده‌ایم. اگر عبارت cust.ID = 10 را مورد استفاده قرار دهید، کامپایلر به شما خطا می‌دهد.

ساخت ویژگی‌های Write-Only

همچنین می‌توان یک ویژگی را به صورت Write-Only نیز تعریف کرد. یعنی این ویژگی تنها قابلیت تنظیم کردن داده را دارد و خواندن اطلاعات از روی آن ممکن نیست. به مثال زیر توجه کنید:

using System;

public class Customer
{
    private int m_id = -1;

    public int ID
    {
        set
        {
            m_id = value;
        }
    }

    private string m_name = string.Empty;

    public string Name
    {
        set
        {
            m_name = value;
        }
    }

    public void DisplayCustomerData()
    {
        Console.WriteLine("ID: {0}, Name:
            {1}", m_id, m_name);
    }
}

public class WriteOnlyCustomerManager
{
    public static void Main()
    {
        Customer cust = new Customer();

        cust.ID = 1;
        cust.Name = "Amelio Rosales";

        cust.DisplayCustomerData();

        Console.ReadKey();
    }
}

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

ساخت ویژگی خود-راه‌انداز

برای راحت‌تر شدن نوشتار برنامه‌ی می‌توان ویژگی‌ها را به صورت خود-راه‌انداز ایجاد کرد. یعنی تعریف یک ویژگی بدون درنظر گرفتن کدهای منطقی معمولی که درون آنها وجود دارد. این نحوه‌ی تعریف ویژگی به عنوان یک سینتکس جدید در 3.0 #C معرفی شد. به مثال زیر توجه کنید:

using System;

public class Customer
{
    public int ID { get; set; }
    public string Name { get; set; }
}

public class AutoImplementedCustomerManager
{
    static void Main()
    {
        Customer cust = new Customer();

        cust.ID = 1;
        cust.Name = "Amelio Rosales";

        Console.WriteLine(
            "ID: {0}, Name: {1}",
            cust.ID,
            cust.Name);

        Console.ReadKey();
    }
}

همانطور که ملاحظه می‌کنید خلاصه‌نویسی بسیار بجایی در ورژن ۳ زبان برنامه‌نویسی #C ایجاد شد که دقیقا عملیاتی مشابه روش قبل را اجرا خواهد کرد.

بسیار عالی! در این بخش نحوه‌ی کار با ویژگی‌ها را فرا گرفتید و متوجه شدید که با استفاده از ویژگی‌ها می‌توان فیلدهایی کنترل‌پذیر یا به عبارتی کپسوله شده (Encapsulation) را ایجاد کنید. در فصل بعدی توضیح مفصلی در ارتباط با Indexer ها ارائه خواهیم داد. با ما همراه باشید.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش سی شارپ (C#) توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.