CodeGym /مدونة جافا /Random-AR /معدّلات الوصول في Java
John Squirrels
مستوى
San Francisco

معدّلات الوصول في Java

نشرت في المجموعة
أهلاً! في درس اليوم، سنتعرف على مفهوم معدّلات الوصول وننظر في أمثلة حول كيفية العمل معها. بالطبع، قول "نتعرف" ليس صحيحًا تمامًا: فأنت بالفعل على دراية بمعظمها من الدروس السابقة. فقط في حالة، دعونا ننعش ذاكرتنا بالنقطة الأكثر أهمية. غالبًا ما يكون الوصول إلى المعدلات عبارة عن كلمات رئيسية تنظم الوصول إلى أجزاء مختلفة من التعليمات البرمجية الخاصة بك. لماذا "في أغلب الأحيان"؟ لأنه يتم تعيين أحدهما افتراضيًا دون استخدام كلمة رئيسية :) تحتوي Java على أربعة معدّلات وصول. ندرجها بالترتيب من الأكثر تقييدًا إلى الأكثر "تساهلا":
  • خاص؛
  • الافتراضي (الحزمة مرئية)؛
  • محمي؛
  • عام.
دعونا نلقي نظرة على كل واحد منهم ونحدد متى قد تكون مفيدة. وسنضرب الأمثلة :)

المعدل الخاص

معدّلات الوصول.  خاص، محمي، افتراضي، عام - 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
   }
}
ومع ذلك، كما ستتذكر من الدرس الخاص بالواجهات، فإن المستخدم لديه حق الوصول إلى الواجهة الخارجية فقط. وأساليبنا الأربعة ليست جزءًا منه. إنها طرق مساعدة: لقد أنشأناها لتحسين إمكانية قراءة التعليمات البرمجية وعدم حشر أربع مهام مختلفة في طريقة واحدة. لا تحتاج إلى منح المستخدم حق الوصول إلى هذه الطرق. إذا كان لدى المستخدمين إمكانية الوصول إلى طريقة 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الحقول والأساليب التي تم وضع علامة عليها بواسطة معدل الوصول المحمي مرئية:
  • ضمن جميع الفئات المدرجة في نفس الباقة الخاصة بنا؛
  • ضمن جميع الطبقات التي ترث طبقتنا.
في البداية، من الصعب أن نتخيل متى قد تكون هناك حاجة لذلك. لا تتفاجأ: هناك حالات استخدام أقل بكثير لـ protected مقارنة بـ Private ، وهي محددة جدًا. تخيل أن لدينا فئة مجردة AbstractSecretAgent تمثل عميلًا سريًا في بعض أجهزة المخابرات، بالإضافة إلى حزمة top_secret تحتوي على هذه الفئة وأحفادها. فئات محددة مثل FBISecretAgent و MI6SecretAgent و MossadSecretAgent وما إلى ذلك ترثها. داخل الفئة المجردة، نريد تنفيذ عداد الوكيل. وسوف تزداد عند إنشاء وكيل جديد في مكان ما في البرنامج. الحزمة 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;
}
وهذا هو نوع المهام المتخصصة التي تتطلب المعدل المحمي :)

الحزمة المرئية المعدلة

التالي في القائمة هو المعدل الافتراضي ، المعروف أيضًا باسم معدل الحزمة المرئي . ولا تتم الإشارة إليه بكلمة رئيسية، نظرًا لأن Java تطبقه افتراضيًا على جميع الحقول والأساليب. إذا كتبت ما يلي في الكود الخاص بك:
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 خاصة داخل حزمة الخدمات . سيكون مسؤولاً عن تحويل البيانات من قاعدة البيانات إلى كائنات Java المألوفة لدينا. فئة مساعد بسيط. عادةً ما نعلن عن جميع الفئات على أنها فئة عامة ClassName ، لكن هذا ليس شرطًا. يمكننا أن نعلن عن فئة المساعد الخاصة بنا ببساطة باسم Class Mapper . في هذه الحالة، فإنه لا يزال يؤدي وظيفته، لكنه غير مرئي لأي شخص خارج حزمة الخدمات !
package services;

class Mapper {
}


package services;

public class CarService {

   Mapper mapper;
}
وإليكم السبب الأساسي: لماذا يحتاج أي شخص خارج الحزمة إلى رؤية فئة مساعدة تعمل فقط مع الفئات الموجودة في تلك الحزمة؟

المعدل العام

وأخيرًا وليس آخرًا، المُعدِّل العام ! لقد قابلت هذا المُعدِّل في أول يوم دراسي لك على CodeGym في المرة الأولى التي قمت فيها بتشغيل public static void main(String[] args) . معدّلات الوصول.  خاص، محمي، افتراضي، عام - 4الآن بعد أن درست الدرس حول الواجهات، أصبح الغرض منه واضحًا لك :) بعد كل شيء، تم إنشاء المعدل العام لإعطاء شيء ما للمستخدمين. على سبيل المثال، واجهة البرنامج الخاص بك. لنفترض أنك كتبت برنامج مترجم يمكنه ترجمة النص الروسي إلى الإنجليزية. لقد قمت بإنشاء طريقة ترجمة (String textIn Russian) التي تنفذ كل المنطق الضروري. لقد قمت بتمييز هذه الطريقة بالكلمة public ، وهي الآن جزء من الواجهة:
public class Translator {

   public String translate(String textInRussian) {

       // Translates text from Russian to English
   }
}
يمكنك ربط هذه الطريقة بالزر "ترجمة" الموجود على الشاشة وبذلك تكون قد انتهيت! يمكن لأي شخص استخدامه. أجزاء التعليمات البرمجية المميزة بالمعدل العام مخصصة للمستخدم النهائي. لتقديم مثال واقعي، الخاص هو لجميع العمليات التي تحدث داخل التلفزيون، ولكن العام هو للأزرار الموجودة على جهاز التحكم عن بعد المستخدم لإدارة التلفزيون. علاوة على ذلك، لا يحتاج المستخدم إلى معرفة كيفية بناء التلفزيون أو كيفية عمله. جهاز التحكم عن بعد عبارة عن مجموعة من الأساليب العامة : on() , off() , nextChannel() , PreviousChannel() , زيادة حجم الصوت() , تقليل حجم الصوت() وما إلى ذلك . لتعزيز ما تعلمته، نقترح عليك مشاهدة درس فيديو من دورة جافا لدينا
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION