
آموزش گام به گام #C (جلسه دهم: ویژگی یا Propertyها)
Propertyها کنترلهایی هستند که برای مقداردهی و خواندن مقادیر از فیلدها مورد استفاده قرار میگیرند. استفاده از propertyها باعث میشوند مقداردهی و خواندن مقدار تسهیل شود. با ما همراه باشید.
جلسه اول: آغاز کار با #C | جلسه ششم: namespaceها | جلسه یازدهم: اندیس گذار یا indexerها | جلسه شانزدهم: استفاده از اتریبیوتها | جلسه بیست و یکم: متدهای بینام یا anonymous |
جلسه دوم: عملگرها، نوعها و متغیرها | جلسه هفتم: مقدمهای بر کلاسهای #C | جلسه دوازدهم: ساختار یا structها | جلسه هفدهم: enumها | جلسه بیست و دوم: موضوعاتی در مورد نوع در #C |
جلسه سوم: عبارات کنترلی - گزینشی | جلسه هشتم: وراثت کلاس در #C | جلسه سیزدهم: واسط یا interfaceها | جلسه هجدهم: عملگرهای overloading | جلسه بیست و سوم: کار با نوعهای nullable |
جلسه چهارم: عبارات کنترلی - حلقهها | جلسه نهم: چندریختی | جلسه چهاردهم: مقدمهای بر delegateها و رویدادها | جلسه نوزدهم: کپسولهسازی | |
جلسه پنجم: متدها | جلسه دهم: ویژگی یا propertyها | جلسه پانزدهم: مقدمهای بر کنترل خطا یا exception | جلسه بیستم: مقدمهای بر generic collectionها |
در این جلسه، Propertyهای #C را به شما خواهیم آموخت. اهداف ما در این جلسه به شرح زیر هستند:
- درک اینکه Propertyها چه کاری انجام میدهند.
- پیادهسازی یک Property.
- ایجاد یک Property فقط خواندنی.
- ایجاد یک Property فقط نوشتنی.
- ایجاد یک Property auto-implemented.
معرفی Propertyها
Propertyها با انجام اعمال خواندن و نوشتن در یک فیلد، فرصتی برای حفاظت از آن فیلد در یک کلاس فراهم میکنند. در زبانهای دیگر، این کار معمولا با متدهای پیادهسازی خاص برنامه به نامهای Getter و Setter انجام میشود.
Propertyهای #C نه تنها به شما اجازه میدهند این حفاظت را ایجاد کنید، بلکه همچنین به شما اجازه میدهند درست همانند یک فیلد، به Property دسترسی داشته باشید.
یک مزیت دیگر Propertyها نسبت به فیلدها این است که میتوانید به مرور زمان، پیادهسازی داخلی آنها را تغییر دهید. در یک فیلد public، نوع داده اصلی مورد استفاده باید همیشه ثابت و یکسان باشد، چون درستی کدهای فراخوانی به این بستگی دارد که فیلدها یکسان باشند.
به هر حال، با استفاده از یک Property، میتوانید پیادهسازی را تغییر دهید.
برای مثال، فرض کنیم یک مشتری دارای ID باشد که در ابتدا به صورت یک int ذخیره شده است، حالا پیشنیازهای برنامه شما به گونهای تغییر میکنند که برای اطمینان از اینکه کد فراخوانی هیچوقت آن ID را به یک مقدار منفی تبدیل نکند، مجبور میشوید یک اعتبارسنجی یا Validation انجام دهید.
اگر آن ID یک فیلد بود، شما هیچوقت نمیتوانستید این کار را انجام دهید، اما Property به شما اجازه میدهد چنین تغییری را بدون شکستن و تغییر کلی کد انجام دهید. حالا، اجازه دهید ببینیم چگونه میتوانیم از Propertyها استفاده کنیم.
عمل کپسولهسازی سنتی بدون استفاده از Propertyها
زبانهایی که Property ندارند برای کپسولهسازی از متدها استفاده میکنند(توابع یا رویهها). ایده اصلی این است که مدیریتی روی مقادیر درون شیء، طراحی state، پرهیز از تخریب حافظه یا دادهها و عمل misuse به وسیله کد فراخوانی انجام شود.
لیست ۱-۱۰ چگونگی عملکرد این متدهای سنتی را نشان میدهد. در این کدها اطلاعات customer از طریق متدهای accessor کپسوله میشوند.
لیست ۱-۱۰. مثالی از دسترسی سنتی به یک فیلد از یک کلاس
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();
}
}
لیست ۱-۱۰ روش و متد سنتی دسترسی به فیلدهای کلاس را نشان میدهد. کلاس customer دارای چهار متد است. دو متد برای هر فیلد private که کلاس آنها را کپسوله میکند: m_id و m_name. همانطور که مشاهده میکند، SetID و SetName مقادیر جدیدی مشخص میکنند و GetID و GetName مقادیر را بازمیگردانند.
ببینید متد Main چگونه متدهای Set را فراخوانی میکند. این فراخوانیها در instance ایجاد شده از کلاس customer(که نام آن cust است)، مقدار ۱ را به mid_id و مقدار “Amelio Rosales” را به m_name اختصاص میدهند.
فراخوانی Console.WriteLine نشان میدهد که m_id و m_name چگونه از cust خوانده میشوند. M_id و m_name به ترتیب توسط متدهای GetID و GetName فراخوانی میشوند.
این یک الگوی مرسوم است که #C آن را به شکل یک ویژگی زبان به نام Property ارائه داده است و در بخش بعدی عملکرد آن را مشاهده خواهید کرد.
کپسولهسازی وضعیت نوعها با استفاده از Propertyها
تمرین دسترسی به داده درون فیلدها از طریق متدها خیلی خوب بود، چون باعث شد مفهوم کپسولهسازی در برنامهنویسی شیءگرا را درک کنید. برای مثال، اگر نوع m_id یا m_name از int به byte تغییر کند، کد فراخوانی باز هم بدون مشکل عمل میکند.
حالا میتوانیم همین کار را به صورت خیلی سادهتر با استفاده از 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();
}
}
لیست ۲-۱۰ چگونگی ایجاد و استفاده از property را نشان میدهد. کلاس customer دارای پیاده سازهای property به نامهای ID و Name میباشد. همچنین فیلدهای private به نامهای m_id و m_name نیز وجود دارند، که به ترتیب ID و Name را کپسوله میکنند.
هر property دارای دو accessor به نامهای get و set است. Get مقدار یک فیلد را بازمیگرداند. Set مقادیری را با استفاده از محتوای درون value در فیلد قرار میدهد، که این قرارگیری با استفاده از کد فراخوانی انجام میشود. Value که در accessor نشان داده شده است یک کلمه رزرو شده مخصوص #C است.
وقتی یک property تعریف میکند، درست همانند وقتی که در فیلد مقداری قرار میدهید به همان صورت به property نیز مقدار دهی کنید. کلاس CustomerManagerWithProperties از propertyهای ID و Name در کلاس Customer استفاده میکند.
اولین خط از متد Main یک شیء Customer به نام cust نمونهسازی میکند. سپس، مقدار فیلدهای m_id و m_name از طریق cust با استفاده از propertyهای ID و Name اختصاص داده میشوند.
برای انجام عمل خواندن از یک property، با property همانند یک فیلد رفتار کنید. دستور Console.WriteLine مقدار فیلدهای m_id و m_name را از طریق cust نمایش میدهد.
این یک property خواندنی / نوشتنی بود، اما همچنین میتوانید propertyهای فقط خواندنی نیز ایجاد کنید، که در بخش بعدی خواهید آموخت.
ایجاد propertyهای فقط خواندنی
Propertyها میتوانند فقط خواندنی باشند. این امر با به کار بردن get accessor به تنهایی در پیادهسازی property انجام میشود. لیست ۳-۱۰ چگونگی ایجاد یک property فقط خواندنی را نشان میدهد.
لیست ۳-۱۰. Propertyهای فقط خواندنی
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();
}
}
کلاس Customer در لیست ۳-۱۰ دارای دو Property فقط خواندنی به نامهای ID و name است. مشاهده میکنید که هر Property فقط خواندنی است چون فقط accessorهای get در آنها قرار دارد. در مقطعی از برنامه، m_id و m_name باید مقدار دهی شوند، که در این مثال این وظیفه به عهده سازنده یا constructor است.
متد Main از کلاس ReadOnlyCustomerManager یک شیء Customer جدید به نام cust نمونهسازی میکند. Cust نمونهسازی شده از سازنده کلاس Customer استفاده میکند، که این سازنده پارامترهای int و String را میگیرد.
در این مثال، مقادیر اختصاص داده شده عبارتاند از ۱ و “Amelio Rosales”. با این حساب فیلدهای m_id و m_name مقداردهی میشوند.
چون Propertyهای ID و Name از کلاس Customer فقط خواندنی هستند، هیچ روش دیگری برای قرار دادن مقدار در فیلدهای m_id و m_name وجود ندارد. اگر در کد بالا مقدار Cust.ID را برابر با ۷ قرار دهید، برنامه کامپایل نمیشود، چون ID فقط خواندنی است.
همین شرایط برای Name نیز صدق میکند. وقتی Propertyهای ID و Name در Console.WriteLine استفاده میشوند، به درستی کار میکنند. این امر به این خاطر است که در این کد فقط عملیات خواندن انجام میشود و فقط accessorهای get از Propertyهای ID و Name فراخوانی میشوند.
ممکن است سوالی که الان برایتان پیش میآید این باشد: اگر یک Property میتواند فقط خواندنی باشد، آیا همچنین میتواند فقط نوشتنی هم باشد؟
پاسخ این سوال بله است و در قسمت بعدی آن را توضیح میدهیم.
ایجاد یک Property فقط نوشتنی
در یک Property فقط نوشتنی میتوانید مقدار اختصاص دهید، اما نمیتوانید آن مقدار را بخوانید. یک Property فقط نوشتنی فقط دارای set accessor است. لیست ۳-۱۰ چگونگی ایجاد و استفاده از Propertyهای فقط نوشتنی را نشان میدهد.
لیست ۴-۱۰. Propertyهای فقط نوشتنی
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();
}
}
این دفعه، get accessor از Propertyهای ID و Name از کلاس Customer که در لیست ۱-۱۰ نشان داده شدند، حذف شدهاند. در عوض Accessorهای set اضافه شدهاند. این accessorها به فیلدهای m_id و m_name مقدار اختصاص میدهند.
متد Main از کلاس WriteOnlyCustomerManager، کلاس Customer را با یک سازنده پیشفرض نمونهسازی میکند. سپس از Propertyهای ID و Name از طریق cust برای اختصاص مقادیر ۱ و “Amelio Rosales” به ترتیب به فیلدهای m_id و m_name از طریق cust استفاده میکند.
در نتیجه set accessor از Propertyهای ID و name از طریق instance یا نمونه cust فراخوانی میشود.
وقتی Propertyهای زیادی در یک کلاس یا struct داشته باشید، همچنین ممکن است کدهای خیلی زیادی نیز در ارتباط با آن Propertyها وجود داشته باشند. در بخش بعدی، خواهید آموخت که چگونه میتوانید با کدهای کمتر Propertyها را بنویسید.
ایجاد auto-implemented Property
الگوهایی که در اینجا میبینید (که در آنها یک Property میتواند Property را با accessorهای Get و Set کپسوله کند) بدون نیاز به منطق دیگری مرسوم و صحیح هستند. اما کدهایی که برای نوشتن این سناریوها مرسوم استفاده شدهاند بیش از آنچه واقعا مورد نیاز است، میباشند.
به همین خاطر C# 3.0 یک syntax جدید برای یک Property معرفی کرده است که auto-implemented property نام دارد. این Property به شما اجازه میدهد تا Propertyها را بدون پیادهسازیهای Accessorهای get و Set ایجاد کنید.
لیست ۵-۱۰ چگونگی افزودن Propertyهای auto-implemented به یک کلاس را نشان میدهد.
لیست ۵-۱۰. Propertyهای auto – implemented
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();
}
}
توجه کنید که accessorهای get و set در لیست ۵-۱۰ هیچ عملیات پیادهسازی ندارند. در auto-implemented property، کامپایلر #C بر اساس همان منطقی که در propertyهای سنتی وجود داشت، فیلد پر شونده را در پشت صحنه ایجاد میکند، اما لازم نیست از همه syntaxهای propertyهای سنتی استفاده کنید.
همانطور که در متد Main میبینید، استفاده از auto-implemented property دقیقا همانند propertyهای سنتی است، که در بخشهای قبلی آنها را آموختید.
خلاصه
حالا دیگر میدانید که propertyها چه استفادهای دارند و چگونه مورد استفاده قرار میگیرند. تکنیکهای سنتی کپسولهسازی از متدهای مجزا و مختلفی استفاده میکنند. Propertyها به شما اجازه میدهند همانند فیلدها با وضعیت اشیاء کار کنید. propertyها میتوانند به صورت فقط خواندنی یا فقط نوشتنی ایجاد شوند.
همچنین آموختید که چگونه میتوان propertyها را با استفاده از auto-implemented propertyها، با کدهای کمتری ایجاد کرد.
منبع: C#-Station
جلسه بعد جلسه قبل
آخرین مطالب

دستور UPDATE در SQL Server برای تغییر دادههای موجود در یک جدول، از دستور UPDATE به شکل زیر استفاده ...

دستور DROP TABLE در SQL Server گاهی، لازم است یک جدول که دیگر استفادهای ندارد را حذف کنید. برای ...

بخش اول از آخرین مبحث دوره جامع آموزش SQL Server در جلسه قبلی بررسی شد. این مبحث که ...
دیدگاه خود را درباره این پست بنویسید