سلامی دیگر به تمام برنامه نویسان. در بخش دوازدهم آموزش در مورد سازنده که یکی از مهمترین متدهای یک کلاس است، صحبت کردیم. اما بحث دیگری که در این مطلب قصد داریم به آن بپردازیم، سطوح دسترسی در ++c یا Access modifiers است. این مفهوم در برنامهنویسی شی گرایی اهمیت بالایی دارد؛ پس توصیه میکنم تا انتهای مطلب همراه ما باشید.
سطح دسترسی چیست؟
با یک مثال ساده مفهموم سطح دسترسی را بیان میکنیم. کلاس زیر را در نظر بگیرید:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class Car { public: int price; std::string name; std::string answer; std::string WhatIsThis(); } std::string Car::WhatIsThis(){ answer = "This is " + name + " and its price is " + std::to_string(price) + " million."; return answer; } |
کلاس Car دارای سه فیلد price و name و answer است و یک متد WhatIsThis است که محتویات کلاس را به فرمتی مشخص توصیف میکند. حال یک شیء از این کلاس داخل main میسازیم:
1 2 3 4 5 6 7 8 9 10 |
int main() { Car c1 = Car(); c1.price = 60; c1.name = "Pezho 405"; cout << c1.WhatIsThis() << endl; getchar(); return 0; } |
1 2 |
This is Pezho 405 and its price is 60 million. |
یک شی از Car با نام c1 ساختیم و طبق توضیحات بخش دوزادهم آموزش، با سازنده پیشفرض آن را مقدار دادیم. سپس فیلدهای price و name را مقداردهی و در نهایت حاصل ()WhatIsThis را چاپ کردیم. اما حاصل خروجی ()WhatIsThis در واقع همان رشته answer است که بصورت یک فیلد در بدنه کلاس است و به راحتی به آن دسترسی داریم و میتوانیم آن را تغییر دهیم.
1 2 3 4 |
Car c1 = Car(); c1.answer = "Rasdino.ir"; cout << c1.answer << endl; |
اما اگر بخواهیم فیلدی تعریف کنیم که تنها در خود کلاس قابل دستیابی باشد و نتوان از بیرون کلاس به آن مقدار داد، باید از سطح دسترسی استفاده کرد.
سطوح دسترسی در ++C
سطوح دسترسی در ++C به سه بخش اصلی تقسیم میشوند:
- سطح دسترسی public: اگر سطح دسترسی public تعریف شود، آن متد یا فیلد در همه جای برنامه و حتی خارج از کلاس کاملا در دسترس قرار میگیرد و هرکجا که بخواهیم به آن دسترسی داریم و میتوانیم آن را بخوانیم یا تغییر دهیم.
- سطح دسترسی private: اگر private استفاده کنیم، تنها و تنها داخل کلاس در دسترس است و در هیچ کجای دیگر در دسترس قرار نمیگیرد.
- سطح دسترسی protected: فیلدها و متدهایی که با protected تعریف شوند، تنها در خود کلاس و کلاسهایی که از کلاس جاری ارث بری کردهاند قابل دستیابی است (مفهموم ارث بری در پست بعدی شرح داده میشود).
نکته: سطوح دسترسی در ++c هم بر روی متدها و هم بر روی فیلدها اعمال میشود.
نکته: اگر سطح دسترسی برای یک فیلد یا متد تعریف نشود بصورت پیشفرض private خواهد بود.
حال مشکل کلاس فوق بصورت زیر قابل حل است:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class Car { public: int price; std::string name; std::string WhatIsThis(); private: std::string answer; } std::string Car::WhatIsThis(){ answer = "This is " + name + " and its price is " + std::to_string(price) + " million."; return answer; } |
سه عنصر price و name و ()WhatIsThis بصورت public و رشته answer بصورت private تعریف شده است. با این تفسیر اگر در شی ساخته شده از Car بخواهیم به answer مقدار دهیم، کامپایلر ارور میدهد.
در شکل فوق کامپایلر غیرقایل دسترس بودن answer را اخطار میدهد. همچنین در شکل زیر میتوان تنها عناصری را دید که در دسترس هستند.
کپسوله سازی
کپسوله سازی به معنای اعمال کنترل بر روی فیلدها است. به عبارتی دیگر اگر بخواهیم روی یک فیلد کنترل داشته باشیم از مفهموم کپسوله سازی استفاده میکنیم. فرض کنید در کلاس Car بخواهیم قیمت ماشین بین 0 تا 150 میلیون باشد و اگر بیش از 150 میلیون بود همان مقدار 150 درون price قرار گیرد.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
class Car { public: std::string name; void setPrice(int pr); std::string WhatIsThis(); private: int price; std::string answer; } std::string Car::WhatIsThis(){ answer = "This is " + name + " and its price is " + std::to_string(price) + " million."; return answer; } void Car::setPrice(int pr){ if(pr>150) price = 150; else if(pr<0) price = 0; else price = pr; } |
با بازنویسی کلاس Car سطح دسترسی price بصورت private تعیین شد و دیگر نمیتوان بیرون از کلاس آن را مقدار داد. از طرفی متدی با سطح دسترسی public با نام setPrice تعریف کردیم که یک پارامتر ورودی به نام pr دارد. حال اگر pr بزرگتر از 150 یا کوچکتر از 0 بود، مقدار price به ترتیب به 150 و 0 محدود میشود. اما اگر pr بین این دو مقدار بود، حاصل آن هرچه باشد در price ریخته میشود. با اینکار ما یک کنترل بر روی price اعمال کردیم و ناچار هستیم در بیرون از کلاس برای مقداردهی آن از setPrice استفاده کنیم.
1 2 3 4 5 |
Car c1 = Car(); c1.name = "Lifan"; c1.setPrice(180); cout << c1.WhatIsThis() << endl; |
1 2 |
This is Lifan and its price is 150 million. |
با توجه به نتیجه دیده شده، چون ما محدوده price را بین 0 تا 150 تعریف کردیم، با وارد کردن 180 در متد setPrice در نهایت نتیجه 150 درون price قرار میگیرد. با اینکار ما متغیر price را به اصطلاح کپسوله کردیم.
خب این بخش از آموزش هم به اتمام رسید و تنها سطح دسترسی protected باقی ماند که در مطلب بعدی در مورد آن صحبت میکنیم. چنانچه هرگونه سؤال یا ایرادی برای شما پیش اومد، ما در بخش کامنت پاسخگوی شما هستیم 🙏