آموزش: آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت چهاردهم - آشنایی با Property ها
چهارشنبه, ۳۰ فروردين ۱۳۹۶، ۰۷:۵۲ ب.ظ
در قسمت قبلی آموزش، در مورد فیلدها و نحوه تعریف آنها در کلاس آشنا شدیم،
اما گاهی اوقات نیاز داریم که بر روند مقداردهی و گرفتن مقدار یک فیلد
نظارت داشته باشیم. زمانی که یک فیلد تعریف می کنیم، عملیات انتساب مقدار و
گرفتن مقدار به صورت مستقیم از داخل فیلد انجام شده و امکان انجام هیچ
گونه نظارتی بر روی این عملیات ها وجود ندارد. برای رفع این مشکل، دو راه
وجود دارد:
- استفاده از متدها برای ست کردن و گرفتن مقدار از فیلد.
- استفاده از Property ها
افرادی که با زبان جاوا آشنا هستند با متدهای get و set در کلاس ها آشنایی دارند. این متدها عملیات خواندن و نوشتن در فیلدها را برای ما انجام می دهند. مثالی از زبان سی شارپ می زنیم. کلاس Person را در نظر بگیرید:
public class Person { public string FirstName; public string LastName; }
این کلاس، ما زمانی که یک شئ از این کلاس می سازیم به صورت مستقیم فیلدها را مقدار دهی کرده یا مقدار آنها را می خوانیم. اما برای کنترل دسترسی به فیلدها، ابتدا باید سطح دسترسی فیلدها را به private تغییر بدیم. زمانی که یک عضو کلاس که
در اینجا فیلدها هستند را به private تغییر می دهیم، آن عضو تنها داخل همان کلاس قابل دسترس خواهد بود. برای اولین قدم، کلاس Person را به صورت زیر تغییر می دهیم:
public class Person { private string firstName; private string lastName; }
به نام گذاری فیلدها دقت کنید، زمانی که فیلدها به private تغییر کردند، نام گذاری بر اساس قاعده camelCase انجام می شود. این قاعده برای کلیه فیلدهای private کلاس ها حکم می کند. البته الزامی به این کار نیست، اما برای رعایت اصول کد نویسی
بهتر است از این قواعد پیروی کنیم. بعضی از برنامه نویس ها ابتدای نام فیلدهای private از کاراکتر _ استفاده می کنند. این موضوع کاملاً دلخواه می باشد، اما سعی کنید در نام گذاری فیلدها public و private تفاوت قایل شوید.
در قدم بعدی باید بتوانیم در خارج از کلاس، عملیات خواندن و مقدار دهی فیلد را انجام دهیم. در روش اول گفتیم که از متدهای get و set برای اینکار استفاده می کنیم. کلاس Person را به صورت زیر تغییر می دهیم:
public class Person { private string firstName; private string lastName; public string GetFirstName() { return firstName; } public void SetFirstName(string value) { firstName = value; } public string GetLastName() { return lastName; } public void SetLastName(string value) { lastName = value; } }
در تصویر زیر، لیست نمایش داده شده برای شئ ای از کلاس Person را مشاهده می کنید:
حال می توانیم عملیات خواندن و نوشتن فیلدها را در خارج از کلاس بوسیله این دو متد انجام دهیم:
var person = new Person(); person.SetFirstName("Hossein"); person.SetLastName("Ahmadi"); Console.WriteLine(person.GetFirstName() + " " + person.GetLastName()); Console.ReadLine();
حال فرض کنید، یک فیلد باید تنها خواندنی باشد، برای اینکار کافیست بخش Set را از کلاس حذف کنید یا فرض کنید عملیات نوشتن باید تنها در داخل خود کلاس انجام شود و از بیرون کلاس دسترسی نوشتن باید بسته شود، برای این کار کافیست که
دسترسی متد Set برای فیلد مورد نظر را به private تغییر دهیم. در مثال زیر عملیات نوشتن برای فیلد firstName به صورت private تعریف شده و فیلد lastName قابلیت نوشتن ندارد:
public class Person { private string firstName; private string lastName; public string GetFirstName() { return firstName; } private void SetFirstName(string value) { firstName = value; } public string GetLastName() { return lastName; } }
استفاده از Property ها
اما در زبان سی شارپ به صورت دیگری می توان این کنترل را انجام داد و آن استفاده از Property ها می باشند. ساختار کلی property ها به صورت زیر می باشد:
{access-modifier} {data-type} {property-name} { [access-modifier] get { // body for get value } [access-modifier] set { // body for set value } }
اما بررسی هر یک از قسمت های ساختار Property:
- access-modifier: سطح دسترسی به Property را تعیین می کند. Property نیز مانند فیلد می تواند سطح دسترسی داشته باشد.
- data-type: نوع Property که یکی از Data Type های دات نت یا کلاسی که به صورت دستی نوشته شده باشد.
- property-name: نام Property، برای نام گذاری Property ها همیشه از قاعده PascalCase استفاده کنید، سطح دسترسی تفاوتی ندارد، همیشه PascalCase تعریف کنید.
- بدنه get: این بدنه، دقیقاً معادل متد Get ایست که در قسمت قبلی تعریف کردیم. شما داخل بدنه get هر دستوری را می توانید بنویسید، در حقیقت این بدنه مانند یک متد عمل کرده و زمانی که شما مقدار Property را می خوانید (مثلاً برای چاپ با دستور
WriteLine) بدنه get اجرا می شود. دقت کنید بدنه get حتماً باید مقداری را با دستور return بر گرداند. همچنین این بدنه می تواند دارای access-modifier باشد، یعنی سطح دسترسی خواندن مقدار را مشخص می کند. در صورتی که سطح دسترسی را
مشخص نکنید به صورت پیش فرض public در نظر گرفته می شود.
- بدنه set: این بدنه، دقیقاً معادل متد Set در مثال قبلی است. زمانی که شما مقداری را داخل Property ست می کنید، بدنه set اجرا می شود. داخل بدنه set پارامتر پیش فرضی وجود دارد به نام value که مقدار ست شده داخل Property داخل آن قرار
گرفته و شما می توانید به آن از داخل بدنه set دسترسی داشته باشید. همچنین می توان برای بدنه set سطح دسترسی را مشخص کرد. در صورتی که سطح دسترسی را مشخص نکنید به صورت پیش فرض public در نظر گرفته می شود.
به مثال کلاس Person بر می گردیم. تصمیم داریم عملیات هایی که در بوسیله متدهای Get و Set انجام دادیم را با Property ها پیاده سازی کنیم. کلاس Person را به صورت زیر تغییر دهید:
public class Person { private string firstName; private string lastName; public string FirstName { get { return firstName; } set { firstName = value; } } public string LastName { get { return lastName; } set { lastName = value; } } }
در کد بالا، دو Property با نام های FirstName و LastName تعریف کردیم که عملیات خواندن و نوشتن از فیلدهای مربوطه را انجام می دهند. نتیجه اعضای نمایش داده شده برای کلاس Person هنگام استفاده از نمونه یا Instance آن را در تصویر زیر مشاهده
می کنید:
در ادامه کد متد Main را به صورت زیر تغییر دهید:
var person = new Person(); person.FirstName = "Hossein"; person.LastName = "Ahmadi"; Console.WriteLine(person.FirstName + " " + person.LastName); Console.ReadKey();
در کد بالا، زمانی که مقدار Hossein را داخل فیلد FirstName ست می کنیم، بدنه set مربوط به خاصیت FirstName اجرا می شود که در این بدنه ما مقدار value که همان مقدار ست شده در هنگام استفاده از کلاس است را داخل فیلد firstName قرار می
دهیم. برای LastName هم به همین صورت است. شاید بپرسید پارامتر value کجا تعریف شده است؟ این پارامتر به صورت پیش فرض برای بدنه set وجود دارد که نگه دارنده مقدار ست شده داخل Property است. همچنین زمانی که داخل دستور WriteLine
مقدار FirstName یا LastName را می خوانیم، بدنه get مربوط به همان Property اجرا می شود. در حقیقت Property ها واسطی میان فیلدها و استفاده کننده از کلاس ها هستند. مانند یک انبار دار که عملیات کنترل ورود و خروج از انبار را کنترل می کند و
عملیات تحویل دادن کالا یا گرفتن کالا و قرار دادن آن در انبار را انجام می دهد.
برای نوشتن Property ها، حتماً نیازی به تعریف Field برای آنها نیست، شما می توانید هر کدی را برای بدنه get یا set بنویسید. برای مثال، می خواهیم به کلاس Person یک Property تعریف کنیم که نام کامل شخص را بر گرداند. نام این خاصیت را FullName
می گذاریم:
public class Person { private string firstName; private string lastName; public string FirstName { get { return firstName; } set { firstName = value; } } public string LastName { get { return lastName; } set { lastName = value; } } public string FullName { get { return FirstName + " " + LastName; } } }
حال کد Main قسمت قبلی را می توان به صورت زیر تغییر داده و از Property جدیدی که تعریف کردیم استفاده کنیم:
var person = new Person(); person.FirstName = "Hossein"; person.LastName = "Ahmadi"; Console.WriteLine(person.FullName); Console.ReadKey();
نگاهی دوباره به کلاس Person و خاصیت FullName می کنیم، اگر دقت کرده باشید این خاصیت تنها بدنه get را دارد و بدنه set را برای آن ننوشتیم. دلیل این امر آن است که FullName تنها برای ترکیبی از firstName و lastName را بر میگرداند. در صورتی که
بخواهیم مقداری داخل FullName بریزیم، با پیغام خطا مواجه می شویم.
Property هایی که بدنه get را ندارند Write-Only و آنهایی که بدنه set را ندارند Read-Only می گوییم. همچنین همانطور که قبلاً هم گفتیم می توانیم علاوه بر خود Property برای هر یک از بدنه های get و set نیز سطح دسترسی مشخص کنیم. برای مثال
میخواهیم خاصیت FirstName تنها داخل خود کلاس قابلیت نوشتن داشته باشد، برای اینکار کافیست بدنه set را به صورت private تعریف کنیم:
public string FirstName { get { return firstName; } private set { firstName = value; } }
Automatic Properties
گاهی اوقات، Property که تعریف می کنیم تنها عملیات خواندن و نوشتن یک فیلد را کنترل می کند. برای مثال، کلاس Person را در نظر بگیرید:
public class Person { private string firstName; public string FirstName { get { return firstName; } set { firstName = value; } } }
کد مربوط به خصوصیت بالا را می توان به شکل زیر نیز نوشت:
public class Person { public string FirstName { get; set; } }
کامپایلر بعد از کامپایل کد بالا، به صورت خودکار یه فیلد برای خاصیت نوشته شده تعریف کرده و بدنه get و set آن را به صورت خودکار می نویسد. از مزیت های Auto-Property ها حجم کد کمتر و البته قابلیت کنترل دسترسی به عملیات های خواندن و نوشتن Property ها می باشد. مثال بالا را جوری تغییر می دهیم که خاصیت FirstName تنها داخل کلاس قابل نوشتن باشد:
public class Person { public string FirstName { get; private set; } }
به این نکته توجه داشته باشید، زمانی که از Auto-Property ها استفاده می کنید، حتماً باید get و set را بنویسید، در غیر اینصورت پیغام خطا دریافت خواهید کرد. البته این مشکل در نسخه 6 زبان سی شارپ برطرف شده است.
در این قسمت با Property ها آشنا شدیم و متوجه شدیم که چگونه می توان عملیات خواندن و نوشتن مقادیر یک کلاس را کنترل کرد. در قسمت بعدی با مفهوم سازنده ها در کلاس ها آشنا شده و به بررسی حالت های مختلف ایجاد شئ از روی کلاس ها خواهیم پرداخت.
منبعprogramming.itpro.ir
- ۹۶/۰۱/۳۰