CodeGym /وبلاگ جاوا /Random-FA /دسترسی به اصلاح کننده ها در جاوا
John Squirrels
مرحله
San Francisco

دسترسی به اصلاح کننده ها در جاوا

در گروه منتشر شد
سلام! در درس امروز با مفهوم اصلاح کننده های دسترسی آشنا می شویم و نمونه هایی از نحوه کار با آنها را در نظر می گیریم. البته، گفتن «آشنایی» کاملاً درست نیست: شما قبلاً با بیشتر آنها در درس های قبلی آشنا هستید. در هر صورت، بیایید خاطره خود را از مهم ترین نکته تجدید کنیم. دسترسی اصلاح‌کننده‌ها اغلب کلمات کلیدی هستند که دسترسی به بخش‌های مختلف کد شما را تنظیم می‌کنند. چرا "اغلب"؟ زیرا یکی از آنها به طور پیش فرض بدون استفاده از کلمه کلیدی تنظیم شده است :) جاوا دارای چهار تغییر دهنده دسترسی است. ما آنها را به ترتیب از محدودترین تا "مهم ترین" فهرست می کنیم:
  • خصوصی؛
  • پیش فرض (بسته قابل مشاهده)؛
  • حفاظت شده؛
  • عمومی.
بیایید نگاهی به هر یک از آنها بیندازیم و تشخیص دهیم که چه زمانی ممکن است مفید باشند. و ما مثال می زنیم :)

اصلاح کننده خصوصی

اصلاح کننده های دسترسی  خصوصی، محافظت شده، پیش فرض، عمومی - 2خصوصی محدودترین اصلاح کننده دسترسی است. دید داده ها و متدها را در یک کلاس محدود می کند. شما این اصلاح کننده را از درس مربوط به گیرنده ها و ستترها می شناسید. این مثال را به خاطر دارید؟
public class Cat {

   public String name;
   public int age;
   public int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }
}

public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";
       cat.age = -1000;
       cat.weight = 0;
   }
}
در درس قبلی به آن پرداختیم. ما در اینجا یک اشتباه جدی مرتکب شدیم: ما داده های خود را عمومی می کنیم، که به برنامه نویسان همکار اجازه می دهد مستقیماً به فیلدها دسترسی داشته باشند و مقادیر آنها را تغییر دهند. علاوه بر این... این مقادیر بدون هیچ گونه بررسی اختصاص داده شده اند. این بدان معنی است که برنامه ما می تواند گربه ای به نام "" با سن -1000 سال و وزن 0 ایجاد کند. برای حل این مشکل از گیرنده ها و تنظیم کننده ها استفاده کردیم و همچنین از اصلاح کننده خصوصی برای محدود کردن دسترسی به داده ها استفاده کردیم.
public class Cat {

   private String name;
   private int age;
   private int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       // input parameter check
       this.name = name;
   }

   public int getAge() {
       return age;
   }

   public void setAge(int age) {
       // input parameter check
       this.age = age;
   }

   public int getWeight() {
       return weight;
   }

   public void setWeight(int weight) {
       // input parameter check
       this.weight = weight;
   }
}
اساساً، محدود کردن دسترسی به فیلدها و پیاده‌سازی گیرنده‌ها و تنظیم‌کننده‌ها، رایج‌ترین نمونه‌های استفاده از خصوصی در کار واقعی هستند. به عبارت دیگر هدف اصلی این اصلاح کننده دستیابی به کپسوله سازی در یک برنامه است. اتفاقاً این فقط برای فیلدها صدق نمی کند. تصور کنید که در برنامه شما روشی وجود دارد که برخی از عملکردهای بسیار پیچیده را پیاده سازی می کند. چه چیزی را می توانیم به عنوان نمونه پیشنهاد کنیم؟ فرض کنید متد readDataFromCollider() شما یک آدرس داده را به عنوان ورودی می پذیرد، داده ها را از برخورد دهنده هادرون بزرگ در قالب بایت می خواند، این داده ها را به متن تبدیل می کند، آن را به یک فایل می نویسد و چاپ می کند. حتی توضیح روش ترسناک به نظر می رسد، اگر چیزی از کد نگوییم :) برای خوانایی بیشتر کد، بهتر است تمام منطق پیچیده روش را در یک مکان ننویسید. در عوض، ما باید عملکرد را به روش های جداگانه تقسیم کنیم. به عنوان مثال، متد readByteData() مسئول خواندن داده ها است، متد convertBytesToSymbols() داده های خوانده شده از برخورد دهنده را به متن تبدیل می کند، متد saveToFile() متن دریافتی را در فایل ذخیره می کند و متد printColliderData() ما را چاپ می کند . فایل اطلاعات. در پایان، روش readDataFromCollider() ما بسیار ساده تر خواهد بود:
public class ColliderUtil {

   public void readDataFromCollider(Path pathToData) {
       byte[] colliderData = readByteData(pathToData);
       String[] textData = convertBytesToSymbols(colliderData);
       File fileWithData = saveToFile(textData);
       printColliderData(fileWithData);
   }

   public byte[] readByteData(Path pathToData) {

       // Reads data in bytes
   }

   public String[] convertBytesToSymbols(byte[] colliderDataInBytes) {

       // Converts bytes to characters
   }

   public File saveToFile(String[] colliderData) {

       // Saves read data to a file
   }

   public void printColliderData(File fileWithColliderData) {

       // Prints data from the file
   }
}
با این حال، همانطور که از درس مربوط به رابط ها به یاد دارید، کاربر فقط به رابط خارجی دسترسی دارد. و 4 روش ما بخشی از آن نیست. آنها روش‌های کمکی هستند: ما آنها را برای بهبود خوانایی کد ایجاد کردیم و چهار کار مختلف را در یک روش جمع نکردیم. نیازی نیست به کاربر اجازه دسترسی به این روش ها را بدهید. اگر کاربران هنگام کار با collider به متد ()convertBytesToSymbols دسترسی داشته باشند، به احتمال زیاد به سادگی با روش گیج می شوند و از خود می پرسند که برای چیست. چه بایت هایی تبدیل می شوند؟ آنها از کجا آمده اند؟ چرا آنها را به متن تبدیل می کنیم؟ منطق اجرا شده در این روش بخشی از رابط کاربری نیست که در معرض دید کاربر قرار می گیرد. فقط متد readDataFromCollider() بخشی از رابط است. پس با این چهار روش «داخلی» چه کنیم؟ درست! از اصلاح کننده خصوصی برای محدود کردن دسترسی به آنها استفاده کنید . انجام این کار به آن‌ها اجازه می‌دهد تا بدون گیج کردن کاربر، که نیازی به دانستن منطق هر روش جداگانه ندارد، کار خود را در کلاس به صورت مسالمت آمیز انجام دهند.
public class ColliderUtil {

   public void readDataFromCollider(Path pathToData) {
       byte[] colliderData = readByteData(pathToData);
       String[] textData = convertBytesToSymbols(colliderData);
       File fileWithData = saveToFile(textData);
       printColliderData(fileWithData);
   }

   private byte[] readByteData(Path pathToData) {
       // Reads data in bytes
   }

   private String[] convertBytesToSymbols(byte[] colliderDataInBytes) {
       // Converts bytes to characters
   }

   private File saveToFile(String[] colliderData) {
       // Saves read data to a file
   }

   private void printColliderData(File fileWithColliderData) {
       // Prints data from the file
   }
}

اصلاح کننده محافظت شده

محدود کننده ترین اصلاح کننده بعدی محافظت شده است . اصلاح کننده های دسترسی  خصوصی، محافظت شده، پیش فرض، عمومی - 3فیلدها و روش های مشخص شده توسط اصلاح کننده دسترسی محافظت شده قابل مشاهده خواهند بود:
  • در تمام کلاس های موجود در بسته مشابه ما؛
  • در تمام کلاس هایی که کلاس ما را به ارث می برند.
در ابتدا، تصور اینکه چه زمانی ممکن است به این مورد نیاز باشد دشوار است. تعجب نکنید: موارد استفاده کمتری برای محافظت شده نسبت به خصوصی وجود دارد و بسیار خاص هستند. تصور کنید که ما یک کلاس انتزاعی AbstractSecretAgent داریم که نماینده یک مامور مخفی در برخی از سرویس های اطلاعاتی است، و همچنین یک بسته top_secret که حاوی این کلاس و فرزندان آن است. کلاس های بتن مانند FBISecretAgent ، MI6SecretAgent ، MossadSecretAgent و غیره آن را به ارث می برند. در داخل کلاس abstract می خواهیم یک شمارنده عامل پیاده سازی کنیم. هنگامی که یک عامل جدید در جایی از برنامه ایجاد شود، افزایش می یابد. بسته top_secret;
public abstract class AbstractSecretAgent {

   public static int agentCount = 0;
}
اما ماموران ما مخفی هستند! این بدان معنی است که آنها و هیچ کس دیگری نباید بدانند که تعداد آنها چقدر است. ما به راحتی می توانیم اصلاح کننده محافظت شده را به قسمت agent_counter اضافه کنیم . سپس نمونه‌هایی از کلاس‌های عامل مخفی دیگر و کلاس‌های دیگری که در بسته top_secret ما قرار دارند می‌توانند ارزش آن را دریافت کنند.
public abstract class AbstractSecretAgent {

   protected static int agent_counter = 0;
}
و این نوعی کار تخصصی است که به اصلاح کننده محافظت شده نیاز دارد :)

بسته قابل مشاهده اصلاح کننده

بعدی در لیست، اصلاح کننده پیش فرض است که به عنوان اصلاح کننده قابل مشاهده بسته نیز شناخته می شود . با یک کلمه کلیدی نشان داده نمی شود، زیرا جاوا آن را به طور پیش فرض در همه زمینه ها و روش ها اعمال می کند. اگر موارد زیر را در کد خود بنویسید:
int x = 10
متغیر x به این بسته دسترسی قابل مشاهده خواهد داشت . به خاطر سپردن کاری که انجام می دهد آسان است. اساسا، پیش فرض = وراثت محافظت شده :) مانند اصلاح کننده محافظت شده ، کاربرد آن محدود است. اغلب، دسترسی پیش‌فرض در بسته‌ای استفاده می‌شود که دارای کلاس‌های کاربردی است که عملکرد همه کلاس‌های دیگر بسته را اجرا نمی‌کنند. بیایید یک مثال بزنیم. تصور کنید که ما یک بسته "خدمات" داریم. این شامل کلاس های مختلفی است که با پایگاه داده کار می کنند. به عنوان مثال، یک کلاس UserService وجود دارد که داده های کاربر را از پایگاه داده می خواند، یک کلاس CarService که داده های ماشین را از همان پایگاه داده می خواند، و کلاس های دیگر، که هر کدام با انواع خاصی از اشیاء کار می کنند و داده های مربوطه را از پایگاه داده می خوانند.
package services;

public class UserService {
}

package services;

public class CarService {
}
اما به راحتی می‌توان داده‌های پایگاه داده در یک قالب باشد و ما به آن در قالب دیگری نیاز داریم. تصور کنید که تاریخ تولد کاربران در پایگاه داده به صورت <TIMESTAMP WITH TIME ZONE> ذخیره می شود...
2014-04-04 20:32:59.390583+02
...و در عوض به ساده ترین شی نیاز داریم - java.util.Date . برای رفع این مشکل در داخل بسته خدمات می توانیم یک کلاس Mapper مخصوص ایجاد کنیم . این مسئول تبدیل داده ها از پایگاه داده به اشیاء جاوای آشنای ما خواهد بود. یک کلاس کمکی ساده ما معمولاً همه کلاس ها را به عنوان کلاس عمومی ClassName اعلام می کنیم ، اما این یک الزام نیست. ما می توانیم کلاس کمکی خود را به سادگی به عنوان کلاس Mapper اعلام کنیم . در این صورت، همچنان کار خود را انجام می دهد، اما برای هیچکس خارج از بسته خدمات قابل مشاهده نیست !
package services;

class Mapper {
}


package services;

public class CarService {

   Mapper mapper;
}
و در اینجا دلیل اصلی این است: چرا هر کسی خارج از یک بسته نیاز به دیدن یک کلاس کمکی دارد که فقط با کلاس های آن بسته کار می کند؟

اصلاح کننده عمومی

و آخرین اما نه کم اهمیت ترین، اصلاح کننده عمومی ! شما در اولین روز مطالعه خود در CodeGym با این اصلاح کننده آشنا شدید، اولین باری که public static void main (String[] args) را اجرا کردید . اصلاح کننده های دسترسی  خصوصی، محافظت شده، پیش فرض، عمومی - 4اکنون که درس مربوط به رابط ها را مطالعه کرده اید، هدف آن برای شما واضح است :) بالاخره، اصلاح کننده عمومی برای ارائه چیزی به کاربران ساخته شده است. به عنوان مثال، رابط برنامه شما. فرض کنید یک برنامه مترجمی نوشته اید که می تواند متن روسی را به انگلیسی ترجمه کند. شما یک متد translate (String textInRussian) ایجاد کردید که تمام منطق لازم را پیاده سازی می کند. شما این روش را با کلمه public علامت گذاری کرده اید و اکنون بخشی از رابط است:
public class Translator {

   public String translate(String textInRussian) {

       // Translates text from Russian to English
   }
}
می‌توانید این روش را به دکمه «ترجمه» روی صفحه متصل کنید و کارتان تمام شد! هر کسی می تواند از آن استفاده کند. بخش هایی از کد که با اصلاح کننده عمومی مشخص شده اند برای کاربر نهایی در نظر گرفته شده است. با ارائه یک مثال واقعی، خصوصی برای تمام فرآیندهایی است که در داخل تلویزیون اتفاق می‌افتد، اما عمومی برای دکمه‌های روی کنترل از راه دور مورد استفاده برای مدیریت تلویزیون است. علاوه بر این، کاربر نیازی ندارد که بداند تلویزیون چگونه ساخته شده یا چگونه کار می کند. کنترل از راه دور مجموعه ای از متدهای عمومی است : on() , off() , nextChannel() , previousChannel() , افزایشVolume() , smallVolume() و غیره . برای تقویت آنچه آموختید، پیشنهاد می کنیم یک درس ویدیویی از دوره جاوا ما
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION